mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-24 13:50:49 +03:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
03681e2592 | ||
|
64fd2e605c | ||
|
c893090668 | ||
|
3f8261e1ca | ||
|
9ce7a1be6e | ||
|
ee72373b8d | ||
|
5c52d14a08 | ||
|
54573faf41 | ||
|
a9cc8b1a3b | ||
|
2b5550fae8 |
@@ -971,3 +971,11 @@ Zoom persistent selection introduces a new structure *Graphic3d_TransformPers* f
|
||||
* Transformation matrix utilities from *OpenGl_Utils* namespace have been moved to *Graphic3d_TransformUtils* and *Graphic3d_TransformUtils.hxx* header respectively.
|
||||
* Matrix stack utilities from *OpenGl_Utils* namespace have been moved to *OpenGl_MatrixStack* class and *OpenGl_MatrixStack.hxx* header respectively.
|
||||
* *OpenGl_View* methods *Begin/EndTransformPersistence* have been removed. Please, use *Graphic3d_TransformPers::Apply()* instead to apply persistence to perspective and world-view projection matrices.
|
||||
Applications that use gp_Quaternion to convert Yaw-Pitch-Roll angles (or other intrinsic Tait-Bryan sequences) may need to be updated to take this change into account.
|
||||
|
||||
|
||||
@subsection Correction of texture mapping of objects
|
||||
|
||||
Interaction of texture and environment texture is fixed. Textured objects have priority over the environment mapping.
|
||||
Redundant enumerations V3d_TypeOfSurface and Graphic3d_TypeOfSurface, class OpenGl_SurfaceDetailState, corresponding methods from Graphic3d_CView, OpenGl_ShaderManager, OpenGl_View, V3d_View, V3d_Viewer are deleted.
|
||||
Draw command VSetTextureMode is deleted.
|
||||
|
@@ -75,4 +75,8 @@ vbsdf r -kd 0.5 0.9 0.3 -ks 0.0 -kr 0.3 -n
|
||||
vbsdf r -fresnel Constant 1.0
|
||||
vsetlocation r 0.5 0.65 0.1
|
||||
|
||||
vclipplane create pln
|
||||
vclipplane change pln equation 0 0 -1 0.1
|
||||
vclipplane set pln object s
|
||||
|
||||
vrenderparams -ray -gi -rayDepth 8
|
||||
|
485
samples/tcl/video.tcl
Normal file
485
samples/tcl/video.tcl
Normal file
@@ -0,0 +1,485 @@
|
||||
pload ALL
|
||||
|
||||
vclear
|
||||
vclose all
|
||||
|
||||
# Declaration global variables
|
||||
global startTimeTyre
|
||||
global currentTimeTyre
|
||||
global endTimeTyre
|
||||
global stepTimeTyre
|
||||
global index
|
||||
|
||||
global paveStartKd
|
||||
global paveStartKt
|
||||
global paveCurrentKd
|
||||
global paveCurrentKt
|
||||
global paveDeltaKd
|
||||
global paveDeltaKt
|
||||
global tyrePlaneStartDistance
|
||||
global tyrePlaneCurrentDistance
|
||||
global tyrePlaneDeltaDistance
|
||||
global tyrePlaneEndDistance
|
||||
|
||||
global folderTyre
|
||||
global folderTyre
|
||||
global folderVideo
|
||||
|
||||
global width
|
||||
global height
|
||||
|
||||
set index 0
|
||||
set startTimeTyre 4805
|
||||
set currentTimeTyre 4805
|
||||
set endTimeTyre 5690
|
||||
set stepTimeTyre 15
|
||||
set SamplesPerPixel 256
|
||||
|
||||
set folderTyre "D:/TmpFiles/for_video/Tyre"
|
||||
set folderEnv "D:/TmpFiles/for_video/Environment"
|
||||
set folderVideo "D:/TmpFiles/for_video/HighQuality"
|
||||
|
||||
set width 1280
|
||||
set height 720
|
||||
#set width 640
|
||||
#set height 360
|
||||
|
||||
# Settings
|
||||
set isEditLight 1
|
||||
set isGI 1
|
||||
set isAnim 1
|
||||
|
||||
set paveStartKd 0.243137
|
||||
set paveStartKt 0.0
|
||||
set paveCurrentKd ${paveStartKd}
|
||||
set paveCurrentKt ${paveStartKt}
|
||||
#set paveDeltaKd 0.0020448142
|
||||
set paveDeltaKd 0.0030392125
|
||||
#set paveDeltaKt 0.0114285714
|
||||
set paveDeltaKt 0.0125
|
||||
set tyrePlaneStartDistance 310
|
||||
set tyrePlaneCurrentDistance ${tyrePlaneStartDistance}
|
||||
set tyrePlaneDeltaDistance 1.5
|
||||
set tyrePlaneEndDistance 190
|
||||
|
||||
vinit name=View1 w=${width} h=${height} t=0 l=0
|
||||
vsetdispmode 1
|
||||
vcamera -persp -fovy 60
|
||||
|
||||
#vzbufftrihedron
|
||||
|
||||
#building0
|
||||
puts "Loading the first building..."
|
||||
vdisplayobj building0 "${folderEnv}/Scene Building0.obj"
|
||||
vbsdf building0 -kd 0.6
|
||||
#grass0
|
||||
puts "Loading the first grass..."
|
||||
vdisplayobj grass0 "${folderEnv}/Scene Grass0.obj"
|
||||
vsetmaterial grass0 plastic
|
||||
vbsdf grass0 -kd 0.113 0.306 0.008
|
||||
#bench0
|
||||
puts "Loading the first bench..."
|
||||
vdisplayobj bench0 "${folderEnv}/Scene Bench0.obj"
|
||||
#bench1
|
||||
puts "Loading the second bench..."
|
||||
vdisplayobj bench1 "${folderEnv}/Scene Bench1.obj"
|
||||
#urn
|
||||
puts "Loading the urn..."
|
||||
vdisplayobj urn "${folderEnv}/Scene Urn.obj"
|
||||
vsetmaterial urn aluminium
|
||||
vbsdf urn -ks 0.6
|
||||
vbsdf urn -roughness 8
|
||||
#pave00
|
||||
puts "Loading the first pave..."
|
||||
vdisplayobj pave00 "${folderEnv}/Scene Pave00.obj"
|
||||
vsetmaterial pave00 stone
|
||||
#pavement0
|
||||
puts "Loading the first pavement..."
|
||||
vdisplayobj pavement0 "${folderEnv}/Scene Pavement0.obj"
|
||||
#pave01
|
||||
puts "Loading the second pave..."
|
||||
vdisplayobj pave01 "${folderEnv}/Scene Pave01.obj"
|
||||
vsetmaterial pave01 stone
|
||||
#Tree00
|
||||
vdisplayobj tree00 "${folderEnv}/Scene Tree00.obj"
|
||||
vbsdf tree00 -ks 0 -kd 1
|
||||
#Tree01
|
||||
vdisplayobj tree01 "${folderEnv}/Scene Tree01.obj"
|
||||
vbsdf tree01 -ks 0 -kd 1
|
||||
|
||||
#building1
|
||||
puts "Loading the second building..."
|
||||
vdisplayobj building1 "${folderEnv}/Scene Building1.obj"
|
||||
vbsdf building1 -kd 0.6
|
||||
#grass1
|
||||
puts "Loading the second grass..."
|
||||
vdisplayobj grass1 "${folderEnv}/Scene Grass1.obj"
|
||||
vsetmaterial grass1 plastic
|
||||
vbsdf grass1 -kd 0.113 0.306 0.008
|
||||
#pave10
|
||||
puts "Loading the second pave..."
|
||||
vdisplayobj pave10 "${folderEnv}/Scene Pave10.obj"
|
||||
vsetmaterial pave10 stone
|
||||
#pavement
|
||||
vdisplayobj pavement1 "${folderEnv}/Scene Pavement1.obj"
|
||||
#pave11
|
||||
vdisplayobj pave11 "${folderEnv}/Scene Pave11.obj"
|
||||
vsetmaterial pave11 stone
|
||||
#Tree10
|
||||
vdisplayobj tree1 "${folderEnv}/Scene Tree10.obj"
|
||||
vbsdf tree1 -ks 0 -kd 1
|
||||
|
||||
#building2
|
||||
puts "Loading the third building..."
|
||||
vdisplayobj building2 "${folderEnv}/Scene Building2.obj"
|
||||
vbsdf building2 -kd 0.4
|
||||
#grass2
|
||||
puts "Loading the third grass..."
|
||||
vdisplayobj grass2 "${folderEnv}/Scene Grass2.obj"
|
||||
vsetmaterial grass2 plastic
|
||||
vbsdf grass2 -kd 0.113 0.306 0.008
|
||||
|
||||
#The ground
|
||||
puts "Loading the ground..."
|
||||
vdisplayobj ground "${folderEnv}/Scene Ground 1.obj"
|
||||
|
||||
vdisplayobj tyre "${folderTyre}/tyre_3.4805.obj"
|
||||
vbsdf tyre -ks 0.3
|
||||
|
||||
if { ${isEditLight} == 1 } {
|
||||
vlight change 0 head 0
|
||||
vlight change 0 sm 0.02
|
||||
vlight change 0 color ANTIQUEWHITE
|
||||
vlight change 0 int 9000
|
||||
vlight change 0 direction 1 0.2 -1
|
||||
}
|
||||
|
||||
vtextureenv on "${folderEnv}/sky_midafternoon.jpg"
|
||||
vrenderparams -env on
|
||||
vclipplane create pln
|
||||
|
||||
if { ${isGI} == 1 } {
|
||||
vrenderparams -ray -gi
|
||||
vrenderparams -brng
|
||||
vrenderparams -rayDepth 3
|
||||
}
|
||||
|
||||
# Animation of movement of the camera.
|
||||
# Prepearing.
|
||||
proc StartMovementOfCamera {thePts theLocalPts theName} {
|
||||
vviewparams -scale 0.76084571141153157
|
||||
vviewparams -proj -0.55490690725196157 0.83079330518538119 0.043137087792445204
|
||||
vviewparams -up 0.0038687080384806026 -0.049275302086848008 0.99877774189374235
|
||||
vviewparams -at 904 -0.0925 3.5
|
||||
vviewparams -eye -1875.1169546272422 4160.7348535943329 219.54166765447638
|
||||
}
|
||||
# Main animation.
|
||||
proc MovementOfCamera {thePts theLocalPts theName} {
|
||||
global index
|
||||
global folderVideo
|
||||
global SamplesPerPixel
|
||||
|
||||
if { ${theLocalPts} < 3.0 } {
|
||||
vshiftcam 0.01
|
||||
} else {
|
||||
vshiftcam 0.005
|
||||
}
|
||||
|
||||
puts $index
|
||||
vrenderparams -spp ${SamplesPerPixel}
|
||||
vdump "${folderVideo}/Res_${index}.png"
|
||||
vrenderparams -spp 1
|
||||
|
||||
set index [expr {${index} + 1}]
|
||||
}
|
||||
|
||||
# Animation of rotation of the camera.
|
||||
# Preparing.
|
||||
proc StartRotationOfCamera {thePts theLocalPts theName} {
|
||||
global index
|
||||
set index 91
|
||||
|
||||
vviewparams -scale 0.17291948306641733
|
||||
vviewparams -proj -0.5549068942726707 0.8307933138774608 0.043137087351443816
|
||||
vviewparams -up 0 0 1
|
||||
vviewparams -at 904 -0.0925 3.5
|
||||
vviewparams -eye 223.11633760908609 1019.310356524007 56.430205481013957
|
||||
}
|
||||
# Main animation.
|
||||
global z
|
||||
set z 3.5
|
||||
proc RotationOfCamera {thePts theLocalPts theName} {
|
||||
global z
|
||||
global width
|
||||
global height
|
||||
global index
|
||||
global folderVideo
|
||||
global SamplesPerPixel
|
||||
|
||||
puts $index
|
||||
|
||||
vmoveto ${width}/2 ${height}/2
|
||||
#vrotate -0.0349066 0 0
|
||||
vrotate -0.1396264 0 0
|
||||
#vrotate 0 -0.004363323 01
|
||||
vrotate 0 -0.017453292 01
|
||||
vviewparams -at 904 -0.0925 ${z} -up 0 0 1
|
||||
|
||||
vrenderparams -spp ${SamplesPerPixel}
|
||||
vfps 1
|
||||
vdump "${folderVideo}/Res_${index}.png"
|
||||
vrenderparams -spp 1
|
||||
|
||||
set index [expr {${index} + 1}]
|
||||
set z [expr {${z} - 1.5}]
|
||||
}
|
||||
|
||||
# Animation of deformation of tyre.
|
||||
# Preparing.
|
||||
proc StartDeformationOfTyre {thePts theLocalPts theName} {
|
||||
global index
|
||||
set index 111
|
||||
|
||||
vviewparams -scale 0.70209376404101775
|
||||
vviewparams -proj 0.29616790541429666 -0.88265982860132486 0.36496054413592205
|
||||
vviewparams -up -0.11609767165456701 0.34600221479170257 0.9310229846763316
|
||||
vviewparams -at 904 -0.092499999999972715 -146.5
|
||||
vviewparams -eye 1269.320051268 -1088.8442787782369 425.17506035310009
|
||||
|
||||
#vviewparams -scale 0.68818212755896502
|
||||
#vviewparams -proj 0.34824854701750618 -0.8177652576045038 0.45823894744470978
|
||||
#vviewparams -up 0 0 1
|
||||
#vviewparams -at 904 -0.092499999999972715 -146.5
|
||||
#vviewparams -eye 1342.2445815876536 -1029.1885184186783 460.15922086382318
|
||||
}
|
||||
# Main animation.
|
||||
proc DeformationOfTyre {thePts theLocalPts theName} {
|
||||
global index
|
||||
global folderTyre
|
||||
global folderVideo
|
||||
global SamplesPerPixel
|
||||
global currentTimeTyre
|
||||
global stepTimeTyre
|
||||
global endTimeTyre
|
||||
|
||||
if { ${currentTimeTyre} <= ${endTimeTyre} } {
|
||||
#erase previous tyre
|
||||
vremove tyre
|
||||
|
||||
#loading current tyre
|
||||
puts "loading tyre_3.${currentTimeTyre}..."
|
||||
vrenderparams -spp 1
|
||||
vdisplayobj tyre "${folderTyre}/tyre_3.${currentTimeTyre}.obj"
|
||||
vbsdf tyre -ks 0.3
|
||||
set bbox [vbounding -print tyre]
|
||||
regexp {tyre+\n([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} ${bbox} full x1 y1 z1 x2 y2 z2
|
||||
vviewparams -at [expr {($x2 + $x1) * 0.5}] [expr {($y2 + $y1) * 0.5}] -131.5 -up 0 0 1
|
||||
if { ${currentTimeTyre} <= 4955 } {
|
||||
vshiftcam 0.01
|
||||
} elseif { ${currentTimeTyre} < 5300 } {
|
||||
vshiftcam 0.005
|
||||
}
|
||||
vrotate -0.003 0 0
|
||||
|
||||
puts $index
|
||||
vrenderparams -spp ${SamplesPerPixel}
|
||||
vfps 1
|
||||
vdump "${folderVideo}/Res_${index}.png"
|
||||
vrenderparams -spp 1
|
||||
|
||||
vrenderparams -spp 1
|
||||
set index [expr {$index + 1}]
|
||||
|
||||
set currentTimeTyre [expr ${currentTimeTyre} + ${stepTimeTyre}]
|
||||
}
|
||||
}
|
||||
|
||||
# Rotation of the camera after deformation.
|
||||
# Preparing.
|
||||
proc StartRotationOfCameraAfterDeformation {thePts theLocalPts theName} {
|
||||
global folderTyre
|
||||
global endTimeTyre
|
||||
global paveStartKd
|
||||
global paveStartKt
|
||||
global index
|
||||
set index 171
|
||||
|
||||
vrenderparams -gi off
|
||||
vremove tyre
|
||||
vdisplayobj tyre "${folderTyre}/tyre_3.${endTimeTyre}.obj"
|
||||
vbsdf tyre -ks 0.3
|
||||
vrenderparams -gi on
|
||||
|
||||
vviewparams -scale 0.89917874503252559
|
||||
vviewparams -proj 0.12928743010777263 -0.87670185844940729 0.46333423336451535
|
||||
vviewparams -up -0.066045096204520176 0.45860503872268371 0.88618252280526355
|
||||
vviewparams -at 1262.0869750976562 14.405502319335938 -131.5
|
||||
vviewparams -eye 1386.6074883792353 -829.97175321148939 314.75078022962293
|
||||
|
||||
#vviewparams -scale 0.9280456841673036
|
||||
#vviewparams -proj 0.18840463572798008 -0.84034129855590489 0.50826193559776089
|
||||
#vviewparams -up -0.10946425274888763 0.49633667496588818 0.86120118581777039
|
||||
#vviewparams -at 1262.0869750976562 14.405502319335938 -131.5
|
||||
#vviewparams -eye 1437.9007346084109 -769.77670424046596 342.79534506079335
|
||||
|
||||
vsetmaterial pave10 glass
|
||||
vbsdf pave10 -absorpcoeff 1.0 -absorpcolor 1.0 1.0 1.0 -fresnel Constant 0.0 -kt ${paveStartKt} -kd ${paveStartKd}
|
||||
}
|
||||
# Main animation.
|
||||
proc RotationOfCameraAfterDeformation {thePts theLocalPts theName} {
|
||||
global index
|
||||
global folderVideo
|
||||
global SamplesPerPixel
|
||||
global tyrePlaneCurrentDistance
|
||||
global tyrePlaneDeltaDistance
|
||||
|
||||
puts $index
|
||||
|
||||
vrotate 0 0.007853985 0
|
||||
|
||||
vclipplane change pln equation -0.1 0.98 0 ${tyrePlaneCurrentDistance}
|
||||
vclipplane set pln object tyre
|
||||
set tyrePlaneCurrentDistance [expr {$tyrePlaneCurrentDistance - $tyrePlaneDeltaDistance}]
|
||||
|
||||
vrenderparams -spp ${SamplesPerPixel}
|
||||
vfps 1
|
||||
vdump "${folderVideo}/Res_${index}.png"
|
||||
vrenderparams -spp 1
|
||||
|
||||
set index [expr {$index + 1}]
|
||||
}
|
||||
|
||||
# Idle animation.
|
||||
# Preparing.
|
||||
proc StartPaveTransparency {thePts theLocalPts theName} {
|
||||
global folderTyre
|
||||
global endTimeTyre
|
||||
global index
|
||||
global tyrePlaneEndDistance
|
||||
set index 252
|
||||
|
||||
vclipplane change pln equation -0.1 0.98 0 190
|
||||
vclipplane set pln object tyre
|
||||
|
||||
vrenderparams -gi off
|
||||
vremove tyre
|
||||
vdisplayobj tyre "${folderTyre}/tyre_3.${endTimeTyre}.obj"
|
||||
vbsdf tyre -ks 0.3
|
||||
vrenderparams -gi on
|
||||
|
||||
vviewparams -scale 0.89917874503252926
|
||||
vviewparams -proj 0.14323443575502989 -0.97766449080860029 -0.15380520090653158
|
||||
vviewparams -up 0.023687355221058894 -0.15197656682365501 0.98810021371272183
|
||||
vviewparams -at 1262.0869750976562 14.405502319335938 -131.5
|
||||
vviewparams -eye 1400.0402582973147 -927.21182359687623 -279.63429694048989
|
||||
|
||||
#vviewparams -scale 0.92804568416730804
|
||||
#vviewparams -proj 0.21658311425190047 -0.97083411217050375 -0.10282451685788761
|
||||
#vviewparams -up 0.023884841470820248 -0.10002361570077746 0.99469834153378234
|
||||
#vviewparams -at 1262.0869750976562 14.405502319335938 -131.5
|
||||
#vviewparams -eye 1464.1960761611324 -891.54882551588094 -227.45286659911696
|
||||
}
|
||||
# Main animation.
|
||||
proc PaveTransparency {thePts theLocalPts theName} {
|
||||
global index
|
||||
global folderVideo
|
||||
global paveStartKd
|
||||
global paveStartKt
|
||||
global paveCurrentKd
|
||||
global paveCurrentKt
|
||||
global paveDeltaKd
|
||||
global paveDeltaKt
|
||||
global SamplesPerPixel
|
||||
|
||||
puts $index
|
||||
|
||||
set paveCurrentKd [expr {$paveCurrentKd - $paveDeltaKd}]
|
||||
set paveCurrentKt [expr {$paveCurrentKt + $paveDeltaKt}]
|
||||
|
||||
vbsdf pave10 -kd ${paveCurrentKd} -kt ${paveCurrentKt}
|
||||
|
||||
vrenderparams -spp ${SamplesPerPixel}
|
||||
vfps 1
|
||||
vdump "${folderVideo}/Res_${index}.png"
|
||||
vrenderparams -spp 1
|
||||
set index [expr {$index + 1}]
|
||||
}
|
||||
|
||||
# Idle animation.
|
||||
# Preparing.
|
||||
proc StartIdleAnim {thePts theLocalPts theName} {
|
||||
global index
|
||||
global endTimeTyre
|
||||
global folderTyre
|
||||
set index 313
|
||||
|
||||
vbsdf pave10 -absorpcoeff 1.0 -absorpcolor 1.0 1.0 1.0 -fresnel Constant 0.0 -kt 1.0 -kd 0.0
|
||||
vclipplane change pln equation -0.1 0.98 0 190
|
||||
vclipplane set pln object tyre
|
||||
|
||||
vrenderparams -gi off
|
||||
vremove tyre
|
||||
vdisplayobj tyre "${folderTyre}/tire_res.obj"
|
||||
vbsdf tyre -ks 0.3
|
||||
vrenderparams -gi on
|
||||
|
||||
vviewparams -scale 0.89917874503252926
|
||||
vviewparams -proj 0.14323443575502989 -0.97766449080860029 -0.15380520090653158
|
||||
vviewparams -up 0.023687358041704527 -0.15197658016980603 0.98810021159237427
|
||||
vviewparams -at 1262.0869750976562 14.405502319335938 -131.5
|
||||
vviewparams -eye 1400.0402582973147 -927.21182359687623 -279.63429694048989
|
||||
|
||||
#vviewparams -scale 0.92804568416730826
|
||||
#vviewparams -proj 0.21658311425190027 -0.97083411217050386 -0.10282451685788763
|
||||
#vviewparams -up 0.023884838973521033 -0.10002359984931483 0.99469834318771899
|
||||
#vviewparams -at 1262.0869750976562 14.405502319335938 -131.5
|
||||
#vviewparams -eye 1464.1960761611322 -891.54882551588094 -227.45286659911696
|
||||
}
|
||||
# Main idle animation.
|
||||
proc IdleAnim {thePts theLocalPts theName} {
|
||||
global index
|
||||
global folderVideo
|
||||
global SamplesPerPixel
|
||||
|
||||
puts $index
|
||||
vrenderparams -spp ${SamplesPerPixel}
|
||||
vdump "${folderVideo}/Res_${index}.png"
|
||||
vrenderparams -spp 1
|
||||
set index [expr {$index + 1}]
|
||||
}
|
||||
|
||||
if { ${isAnim} == 1 } {
|
||||
set startTimeMovCam 0.0
|
||||
set endTimeMovCam 4.5
|
||||
set endTimeRotation 4.8
|
||||
set endTimeDeformations 8.0
|
||||
|
||||
vlight change 0 head 0
|
||||
vrenderparams -spp 1
|
||||
|
||||
vanim movcam -reset -onRedraw MovementOfCamera -onStart StartMovementOfCamera
|
||||
vanim animcam0 -reset -addSlice 0.0 4.5 movcam
|
||||
#vanim -play animcam0 -playFps 20
|
||||
|
||||
vanim rotcam -reset -onRedraw RotationOfCamera -onStart StartRotationOfCamera
|
||||
vanim animcam1 -reset -addSlice 0.0 1.0 rotcam
|
||||
#vanim -play animcam1 -playFps 20
|
||||
|
||||
vanim deftyre -reset -onRedraw DeformationOfTyre -onStart StartDeformationOfTyre
|
||||
vanim animdef -reset -addSlice 0.0 3.0 deftyre
|
||||
#vanim -play animdef -playFps 20
|
||||
|
||||
vanim rotCamAfterDef -reset -onRedraw RotationOfCameraAfterDeformation -onStart StartRotationOfCameraAfterDeformation
|
||||
vanim animRotCamAfterDef -reset -addSlice 0.0 4.0 rotCamAfterDef
|
||||
vanim -play animRotCamAfterDef -playFps 20
|
||||
|
||||
vanim pavetrans -reset -onRedraw PaveTransparency -onStart StartPaveTransparency
|
||||
vanim animpavetrans -reset -addSlice 0.0 3.0 pavetrans
|
||||
vanim -play animpavetrans -playFps 20
|
||||
|
||||
vanim idle -reset -onRedraw IdleAnim -onStart StartIdleAnim
|
||||
vanim animidle -reset -addSlice 0.0 2.0 idle
|
||||
vanim -play animidle -playFps 20
|
||||
|
||||
vrenderparams -spp 1
|
||||
}
|
@@ -160,7 +160,6 @@ Graphic3d_TypeOfReflection.hxx
|
||||
Graphic3d_TypeOfShaderObject.hxx
|
||||
Graphic3d_TypeOfShadingModel.hxx
|
||||
Graphic3d_TypeOfStructure.hxx
|
||||
Graphic3d_TypeOfSurfaceDetail.hxx
|
||||
Graphic3d_TypeOfTexture.hxx
|
||||
Graphic3d_TypeOfTextureFilter.hxx
|
||||
Graphic3d_TypeOfTextureMode.hxx
|
||||
|
@@ -54,7 +54,7 @@ public:
|
||||
}
|
||||
|
||||
//! Pass clip planes to the associated graphic driver structure
|
||||
void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) { myClipPlanes = thePlanes; }
|
||||
virtual void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) { myClipPlanes = thePlanes; }
|
||||
|
||||
//! @return bounding box of this presentation
|
||||
const Graphic3d_BndBox4f& BoundingBox() const
|
||||
|
@@ -1068,7 +1068,6 @@ void Graphic3d_CView::CopySettings (const Handle(Graphic3d_CView)& theOther)
|
||||
SetTextureEnv (theOther->TextureEnv());
|
||||
SetCullingEnabled (theOther->IsCullingEnabled());
|
||||
SetShadingModel (theOther->ShadingModel());
|
||||
SetSurfaceDetailType (theOther->SurfaceDetailType());
|
||||
SetBackfacingModel (theOther->BackfacingModel());
|
||||
SetCamera (new Graphic3d_Camera (theOther->Camera()));
|
||||
SetBackZClippingOn (theOther->BackZClippingIsOn());
|
||||
|
@@ -40,7 +40,6 @@
|
||||
#include <Graphic3d_TypeOfAnswer.hxx>
|
||||
#include <Graphic3d_TypeOfBackfacingModel.hxx>
|
||||
#include <Graphic3d_TypeOfShadingModel.hxx>
|
||||
#include <Graphic3d_TypeOfSurfaceDetail.hxx>
|
||||
#include <Graphic3d_TypeOfVisualization.hxx>
|
||||
#include <Graphic3d_Vec3.hxx>
|
||||
#include <Graphic3d_ZLayerId.hxx>
|
||||
@@ -434,12 +433,6 @@ public:
|
||||
//! Sets shading model of the view.
|
||||
virtual void SetShadingModel (const Graphic3d_TypeOfShadingModel theModel) = 0;
|
||||
|
||||
//! Returns surface detail type of the view.
|
||||
virtual Graphic3d_TypeOfSurfaceDetail SurfaceDetailType() const = 0;
|
||||
|
||||
//! Sets surface detail type of the view.
|
||||
virtual void SetSurfaceDetailType (const Graphic3d_TypeOfSurfaceDetail theType) = 0;
|
||||
|
||||
//! Return backfacing model used for the view.
|
||||
virtual Graphic3d_TypeOfBackfacingModel BackfacingModel() const = 0;
|
||||
|
||||
|
@@ -61,6 +61,8 @@ public:
|
||||
IsTransparentShadowEnabled (Standard_False),
|
||||
UseEnvironmentMapBackground (Standard_False),
|
||||
CoherentPathTracingMode (Standard_False),
|
||||
IsGIFilteringEnabled (Standard_False),
|
||||
RadianceClampValue (10.0),
|
||||
// stereoscopic parameters
|
||||
StereoMode (Graphic3d_StereoMode_QuadBuffer),
|
||||
AnaglyphFilter (Anaglyph_RedCyan_Optimized),
|
||||
@@ -99,6 +101,8 @@ public:
|
||||
Standard_Boolean IsTransparentShadowEnabled; //!< enables/disables light propagation through transparent media, False by default
|
||||
Standard_Boolean UseEnvironmentMapBackground; //!< enables/disables environment map background
|
||||
Standard_Boolean CoherentPathTracingMode; //!< enables/disables 'coherent' tracing mode (single RNG seed within 16x16 image blocks)
|
||||
Standard_Boolean IsGIFilteringEnabled; //!< enables/disables post-processing of GI rendering results
|
||||
Standard_Real RadianceClampValue; //!< maximum radiance value which will not be clamped.
|
||||
|
||||
Graphic3d_StereoMode StereoMode; //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
|
||||
Anaglyph AnaglyphFilter; //!< filter for anaglyph output, Anaglyph_RedCyan_Optimized by default
|
||||
|
@@ -1,32 +0,0 @@
|
||||
// Created on: 1991-10-07
|
||||
// Created by: NW,JPB,CAL
|
||||
// Copyright (c) 1991-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Graphic3d_TypeOfSurfaceDetail_HeaderFile
|
||||
#define _Graphic3d_TypeOfSurfaceDetail_HeaderFile
|
||||
|
||||
//! Modes of visualisation of objects in a view
|
||||
//!
|
||||
//! TOD_NONE no texture mapping
|
||||
//! TOD_ENVIRONMENT only environnement mapping
|
||||
//! TOD_ALL environnement + texture mapping
|
||||
enum Graphic3d_TypeOfSurfaceDetail
|
||||
{
|
||||
Graphic3d_TOD_NONE,
|
||||
Graphic3d_TOD_ENVIRONMENT,
|
||||
Graphic3d_TOD_ALL
|
||||
};
|
||||
|
||||
#endif // _Graphic3d_TypeOfSurfaceDetail_HeaderFile
|
@@ -35,7 +35,8 @@ struct Graphic3d_ZLayerSettings
|
||||
Flags (Graphic3d_ZLayerDepthTest
|
||||
| Graphic3d_ZLayerDepthWrite
|
||||
| Graphic3d_ZLayerDepthClear),
|
||||
IsImmediate (false)
|
||||
IsImmediate (false),
|
||||
UseEnvironmentTexture (true)
|
||||
{}
|
||||
|
||||
//! Returns true if theSetting is enabled.
|
||||
@@ -76,10 +77,11 @@ struct Graphic3d_ZLayerSettings
|
||||
|
||||
public:
|
||||
|
||||
Standard_ShortReal DepthOffsetFactor; //!< factor argument value for OpenGl glPolygonOffset function
|
||||
Standard_ShortReal DepthOffsetUnits; //!< units argument value for OpenGl glPolygonOffset function
|
||||
Standard_Integer Flags; //!< storage field for settings
|
||||
bool IsImmediate; //!< immediate layer will be drawn after all normal layers
|
||||
Standard_ShortReal DepthOffsetFactor; //!< factor argument value for OpenGl glPolygonOffset function
|
||||
Standard_ShortReal DepthOffsetUnits; //!< units argument value for OpenGl glPolygonOffset function
|
||||
Standard_Integer Flags; //!< storage field for settings
|
||||
bool IsImmediate; //!< immediate layer will be drawn after all normal layers
|
||||
bool UseEnvironmentTexture; //!< flag to allow/prevent environment texture mapping usage for specific layer
|
||||
|
||||
};
|
||||
|
||||
|
16
src/MeshVS/CafShapePrs.cpp
Normal file
16
src/MeshVS/CafShapePrs.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <CafShapePrs.h>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(CafShapePrs, XCAFPrs_AISObject)
|
||||
|
||||
// =======================================================================
|
||||
// function : CafShapePrs
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
CafShapePrs::CafShapePrs (const TDF_Label& theLabel,
|
||||
const XCAFPrs_Style& theStyle,
|
||||
const Graphic3d_MaterialAspect& theMaterial)
|
||||
: XCAFPrs_AISObject (theLabel),
|
||||
myDefStyle (theStyle)
|
||||
{
|
||||
SetMaterial (theMaterial);
|
||||
}
|
62
src/MeshVS/CafShapePrs.h
Normal file
62
src/MeshVS/CafShapePrs.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef CafShapePrs_Header
|
||||
#define CafShapePrs_Header
|
||||
|
||||
#include <XCAFPrs_AISObject.hxx>
|
||||
#include <XCAFPrs_Style.hxx>
|
||||
|
||||
typedef NCollection_DataMap<TopoDS_Shape, Handle(AIS_ColoredDrawer), TopTools_ShapeMapHasher> CafDataMapOfShapeColor;
|
||||
|
||||
//! Interactive object for shape in DECAF document.
|
||||
class CafShapePrs : public XCAFPrs_AISObject
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor.
|
||||
Standard_EXPORT CafShapePrs (const TDF_Label& theLabel,
|
||||
const XCAFPrs_Style& theStyle,
|
||||
const Graphic3d_MaterialAspect& theMaterial);
|
||||
|
||||
//! Search custom aspect for specified shape.
|
||||
Standard_Boolean FindCustomAspects (const TopoDS_Shape& theShape,
|
||||
Handle(AIS_ColoredDrawer)& theAspects) const
|
||||
{
|
||||
return myShapeColors.Find (theShape, theAspects);
|
||||
}
|
||||
|
||||
//! Access the styles map.
|
||||
const CafDataMapOfShapeColor& ShapeColors() const { return myShapeColors; }
|
||||
|
||||
//! Override default style.
|
||||
virtual void DefaultStyle (XCAFPrs_Style& theStyle) const Standard_OVERRIDE
|
||||
{
|
||||
theStyle = myDefStyle;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
XCAFPrs_Style myDefStyle; //!< default style
|
||||
|
||||
public: //! @name Declaration of CASCADE RTTI
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(CafShapePrs, XCAFPrs_AISObject)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE (CafShapePrs, XCAFPrs_AISObject)
|
||||
|
||||
#endif
|
@@ -84,3 +84,19 @@ MeshVS_TwoNodes.hxx
|
||||
MeshVS_TwoNodesHasher.hxx
|
||||
MeshVS_VectorPrsBuilder.cxx
|
||||
MeshVS_VectorPrsBuilder.hxx
|
||||
|
||||
MeshDataSource.h
|
||||
MeshDataSource.cpp
|
||||
ObjDataSource.h
|
||||
ObjDataSource.cpp
|
||||
MeshScalarProperty.h
|
||||
MeshPresentation.h
|
||||
MeshPresentation.cpp
|
||||
MeshPrsBuilder.h
|
||||
MeshPrsBuilder.cpp
|
||||
ObjDataWriter.h
|
||||
ObjDataWriter.cpp
|
||||
FaceIterator.h
|
||||
FaceIterator.cpp
|
||||
CafShapePrs.h
|
||||
CafShapePrs.cpp
|
||||
|
150
src/MeshVS/FaceIterator.cpp
Normal file
150
src/MeshVS/FaceIterator.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <FaceIterator.h>
|
||||
|
||||
#include <AIS_ColoredShape.hxx>
|
||||
#include <AIS_ConnectedInteractive.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepLProp_SLProps.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <CafShapePrs.h>
|
||||
#include <Poly_Array1OfTriangle.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
|
||||
// =======================================================================
|
||||
// function : FaceIterator
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
FaceIterator::FaceIterator (const AIS_ListOfInteractive& thePrsList)
|
||||
: myPrsIter (thePrsList)
|
||||
{
|
||||
Next();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Next
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void FaceIterator::Next()
|
||||
{
|
||||
for (; myPrsIter.More(); myPrsIter.Next())
|
||||
{
|
||||
Handle(AIS_ConnectedInteractive) aConnected = Handle(AIS_ConnectedInteractive)::DownCast (myPrsIter.Value());
|
||||
Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (!aConnected.IsNull() ? aConnected->ConnectedTo() : myPrsIter.Value());
|
||||
|
||||
ShapePrs = Handle(CafShapePrs)::DownCast (aShapePrs);
|
||||
myPrsLocation = TopLoc_Location();
|
||||
if (ShapePrs.IsNull())
|
||||
{
|
||||
Triangulation.Nullify();
|
||||
Face.Nullify();
|
||||
myFacesMap.Clear();
|
||||
continue;
|
||||
}
|
||||
else if (!aConnected.IsNull()
|
||||
&& aConnected->LocalTransformation().Form() != gp_Identity)
|
||||
{
|
||||
myPrsLocation = TopLoc_Location (aConnected->LocalTransformation());
|
||||
}
|
||||
|
||||
TopoDS_Shape aShape = ShapePrs->Shape();
|
||||
if (aShape.IsNull())
|
||||
{
|
||||
Triangulation.Nullify();
|
||||
Face.Nullify();
|
||||
myFacesMap.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (myFacesMap.IsEmpty())
|
||||
{
|
||||
// should be replaced by TopTools_OrientedShapeMaphasher to export correctly composed solids
|
||||
// (e.g. shared face should be exported twice with different order of triangles
|
||||
// and possible unique color)
|
||||
TopExp::MapShapesAndAncestors (aShape, TopAbs_FACE, TopAbs_SHAPE, myFacesMap);
|
||||
if (myFacesMap.IsEmpty())
|
||||
{
|
||||
Triangulation.Nullify();
|
||||
Face.Nullify();
|
||||
continue;
|
||||
}
|
||||
|
||||
// register compounds generated by XCAFPrs_AISObject for grouping elements with the same style
|
||||
const CafDataMapOfShapeColor& aColorsMap = ShapePrs->ShapeColors();
|
||||
for (CafDataMapOfShapeColor::Iterator aShapeMapIter (aColorsMap); aShapeMapIter.More(); aShapeMapIter.Next())
|
||||
{
|
||||
if (aShapeMapIter.Key().ShapeType() != TopAbs_COMPOUND
|
||||
|| aShapeMapIter.Key().IsEqual (aShape))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (TopExp_Explorer aCompFaceIter (aShapeMapIter.Key(), TopAbs_FACE); aCompFaceIter.More(); aCompFaceIter.Next())
|
||||
{
|
||||
const Standard_Integer anIndex = myFacesMap.FindIndex (aCompFaceIter.Current());
|
||||
if (anIndex != 0)
|
||||
{
|
||||
myFacesMap.ChangeFromIndex (anIndex).Append (aShapeMapIter.Key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myFaceIter = TopTools_IndexedDataMapOfShapeListOfShape::Iterator (myFacesMap);
|
||||
}
|
||||
for (; myFaceIter.More(); myFaceIter.Next())
|
||||
{
|
||||
Face = TopoDS::Face (myFaceIter.Key());
|
||||
Triangulation = BRep_Tool::Triangulation (Face, myFaceLocation);
|
||||
Trsf = myPrsLocation.Multiplied (myFaceLocation).Transformation();
|
||||
if ( Triangulation.IsNull()
|
||||
|| Triangulation->Triangles().Length() == 0
|
||||
|| !Triangulation->HasUVNodes())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(AIS_ColoredDrawer) aCustomDrawer;
|
||||
if (!ShapePrs->FindCustomAspects (Face, aCustomDrawer))
|
||||
{
|
||||
for (TopTools_ListOfShape::Iterator aParentIter (myFaceIter.Value()); aParentIter.More(); aParentIter.Next())
|
||||
{
|
||||
if (ShapePrs->FindCustomAspects (aParentIter.Value(), aCustomDrawer))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aCustomDrawer.IsNull())
|
||||
{
|
||||
ShapePrs->FindCustomAspects (aShape, aCustomDrawer);
|
||||
}
|
||||
}
|
||||
Drawer = aCustomDrawer;
|
||||
if (Drawer.IsNull())
|
||||
{
|
||||
Drawer = aShapePrs->Attributes();
|
||||
}
|
||||
|
||||
myFaceIter.Next();
|
||||
return;
|
||||
}
|
||||
Triangulation.Nullify();
|
||||
Face.Nullify();
|
||||
myFacesMap.Clear();
|
||||
myFaceIter = TopTools_IndexedDataMapOfShapeListOfShape::Iterator();
|
||||
Drawer.Nullify();
|
||||
}
|
||||
}
|
64
src/MeshVS/FaceIterator.h
Normal file
64
src/MeshVS/FaceIterator.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef FaceIterator_H
|
||||
#define FaceIterator_H
|
||||
|
||||
#include <AIS_ListOfInteractive.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
||||
|
||||
class CafShapePrs;
|
||||
class Prs3d_Drawer;
|
||||
class Poly_Triangulation;
|
||||
|
||||
//! Auxiliary class to iterate through triangulated faces in presentations list.
|
||||
class FaceIterator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
Handle(CafShapePrs) ShapePrs;
|
||||
TopoDS_Face Face;
|
||||
Handle(Prs3d_Drawer) Drawer;
|
||||
Handle(Poly_Triangulation) Triangulation;
|
||||
gp_Trsf Trsf;
|
||||
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Standard_EXPORT FaceIterator (const AIS_ListOfInteractive& thePrsList);
|
||||
|
||||
//! Return true if iterator points to the valid triangulation.
|
||||
bool More() const
|
||||
{
|
||||
return !Triangulation.IsNull();
|
||||
}
|
||||
|
||||
//! Find next value.
|
||||
Standard_EXPORT void Next();
|
||||
|
||||
private:
|
||||
|
||||
AIS_ListOfInteractive::Iterator myPrsIter;
|
||||
TopLoc_Location myPrsLocation;
|
||||
TopTools_IndexedDataMapOfShapeListOfShape myFacesMap;
|
||||
TopTools_IndexedDataMapOfShapeListOfShape::Iterator myFaceIter;
|
||||
TopLoc_Location myFaceLocation;
|
||||
|
||||
};
|
||||
|
||||
#endif // FaceIterator_H
|
278
src/MeshVS/MeshDataSource.cpp
Normal file
278
src/MeshVS/MeshDataSource.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
// Copyright (c) 2014-2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <MeshDataSource.h>
|
||||
|
||||
#include <Standard_CLocaleSentry.hxx>
|
||||
#include <MeshVS_Drawer.hxx>
|
||||
#include <MeshVS_DrawerAttribute.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Message_ProgressSentry.hxx>
|
||||
#include <NCollection_Handle.hxx>
|
||||
#include <TColgp_SequenceOfXYZ.hxx>
|
||||
#include <TColStd_DataMapOfIntegerReal.hxx>
|
||||
#include <TColStd_DataMapOfIntegerInteger.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
#include <Quantity_Color.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(MeshScalarProperty, Standard_Transient)
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(MeshDataSource, MeshVS_DataSource)
|
||||
|
||||
//================================================================
|
||||
// Function : Constructor
|
||||
// Purpose :
|
||||
//================================================================
|
||||
MeshDataSource::MeshDataSource()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : Clear
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshDataSource::Clear()
|
||||
{
|
||||
myUsedNodes.Clear();
|
||||
myFreeNodes.Clear();
|
||||
myUsedElements.Clear();
|
||||
myComments.Clear();
|
||||
myNodes.Clear();
|
||||
myNormals.Clear();
|
||||
myNodesUV.Clear();
|
||||
myNodalColors.Clear();
|
||||
myElements.Clear();
|
||||
myNodalQuantities.Clear();
|
||||
myElementalQuantities.Clear();
|
||||
myGroups.Clear();
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : GetGeom
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Standard_Boolean MeshDataSource::GetGeom (const Standard_Integer theID,
|
||||
const Standard_Boolean theIsElement,
|
||||
TColStd_Array1OfReal& theCoords,
|
||||
Standard_Integer& theNbNodes,
|
||||
MeshVS_EntityType& theType) const
|
||||
{
|
||||
const Standard_Integer aLow = theCoords.Lower();
|
||||
if (theIsElement)
|
||||
{
|
||||
if (theID < 0 || theID >= myUsedElements.Extent())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const Graphic3d_Vec4i& anElem = myElements.Value (theID);
|
||||
theType = MeshVS_ET_Face;
|
||||
theNbNodes = anElem[3] == -1 ? 3 : 4;
|
||||
for (Standard_Integer aNodeIter = 0, aCoordIter = aLow - 1; aNodeIter < theNbNodes; ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNode = myNodes.Value (anElem[aNodeIter]);
|
||||
theCoords (++aCoordIter) = aNode.x();
|
||||
theCoords (++aCoordIter) = aNode.y();
|
||||
theCoords (++aCoordIter) = aNode.z();
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
else if (theID < 0 || theID >= myUsedNodes.Extent())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
theType = MeshVS_ET_Node;
|
||||
theNbNodes = 1;
|
||||
const Graphic3d_Vec3& aNode = myNodes.Value (theID);
|
||||
theCoords (aLow) = aNode.x();
|
||||
theCoords (aLow + 1) = aNode.y();
|
||||
theCoords (aLow + 2) = aNode.z();
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : GetNodesByElement
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Standard_Boolean MeshDataSource::GetNodesByElement (const Standard_Integer theID,
|
||||
TColStd_Array1OfInteger& theNodeIDs,
|
||||
Standard_Integer& theNbNodes) const
|
||||
{
|
||||
if (theID < 0 || theID >= myUsedElements.Extent())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const Graphic3d_Vec4i& anElem = myElements.Value (theID);
|
||||
theNbNodes = anElem[3] == -1 ? 3 : 4;
|
||||
if (theNodeIDs.Length() < theNbNodes)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const Standard_Integer aLow = theNodeIDs.Lower();
|
||||
theNodeIDs (aLow) = anElem[0];
|
||||
theNodeIDs (aLow + 1) = anElem[1];
|
||||
theNodeIDs (aLow + 2) = anElem[2];
|
||||
if (theNbNodes == 4)
|
||||
{
|
||||
theNodeIDs (aLow + 3) = anElem[3];
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : GetNodeNormal
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Standard_Boolean MeshDataSource::GetNodeNormal (const Standard_Integer theRankNode,
|
||||
const Standard_Integer theElementId,
|
||||
Standard_Real& theNX,
|
||||
Standard_Real& theNY,
|
||||
Standard_Real& theNZ) const
|
||||
{
|
||||
if (theElementId < 0 || theElementId >= myUsedElements.Extent()
|
||||
|| !HasNormals())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const Graphic3d_Vec4i& anElem = myElements.Value (theElementId);
|
||||
const Graphic3d_Vec3& aNorm = myNormals.Value (anElem[theRankNode - 1]);
|
||||
theNX = Standard_Real(aNorm.x());
|
||||
theNY = Standard_Real(aNorm.y());
|
||||
theNZ = Standard_Real(aNorm.z());
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
inline void truncateToRange (Standard_Real& theValue,
|
||||
const Standard_Real theLower,
|
||||
const Standard_Real theUpper)
|
||||
{
|
||||
if (theValue <= theLower)
|
||||
{
|
||||
theValue = theLower;
|
||||
}
|
||||
else if (theValue >= theUpper)
|
||||
{
|
||||
theValue = theUpper;
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : FillPropertyBuilder
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshDataSource::FillPropertyBuilder (const Handle(MeshVS_PrsBuilder)& theBuilder,
|
||||
const Handle(MeshScalarProperty)& theProperty) const
|
||||
{
|
||||
Handle(MeshVS_NodalColorPrsBuilder) aNodalBuilder = Handle(MeshVS_NodalColorPrsBuilder) ::DownCast (theBuilder);
|
||||
Handle(MeshVS_ElementalColorPrsBuilder) anElemBuilder = Handle(MeshVS_ElementalColorPrsBuilder)::DownCast (theBuilder);
|
||||
if ((aNodalBuilder.IsNull() && anElemBuilder.IsNull())
|
||||
|| theProperty.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//theBuilder->UseTexture (Standard_True);
|
||||
const Standard_Boolean isGrayscale = (theProperty->Name() == "intensity");
|
||||
|
||||
const Standard_Real aLowerValue = isGrayscale ? 0.0 : theProperty->LowerValue();
|
||||
const Standard_Real aRange = isGrayscale ? 1.0 : theProperty->UpperValue() - theProperty->LowerValue();
|
||||
|
||||
const Graphic3d_Vec3d aScale00 = isGrayscale ? Graphic3d_Vec3d (0.0, 0.0, 0.0) : Graphic3d_Vec3d (0.0, 0.0, 1.0);
|
||||
const Graphic3d_Vec3d aScale05 = isGrayscale ? Graphic3d_Vec3d (0.5, 0.5, 0.5) : Graphic3d_Vec3d (0.0, 1.0, 0.0);
|
||||
const Graphic3d_Vec3d aScale10 = isGrayscale ? Graphic3d_Vec3d (1.0, 1.0, 1.0) : Graphic3d_Vec3d (1.0, 0.0, 0.0);
|
||||
Graphic3d_Vec3d aColor;
|
||||
for (Standard_Integer anElemIter = theProperty->LowerIndex(); anElemIter <= theProperty->UpperIndex(); ++anElemIter)
|
||||
{
|
||||
if (aRange <= Precision::Confusion())
|
||||
{
|
||||
aColor = aScale00;
|
||||
}
|
||||
else
|
||||
{
|
||||
Standard_Real aValue = (theProperty->Value (anElemIter) - aLowerValue) / aRange;
|
||||
if (aValue < 0.5)
|
||||
{
|
||||
aValue *= 2.0;
|
||||
aColor = aScale00 * (1.0 - aValue) + aScale05 * aValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
aValue = (aValue - 0.5) * 2.0;
|
||||
aColor = aScale05 * (1.0 - aValue) + aScale10 * aValue;
|
||||
}
|
||||
truncateToRange (aColor.r(), 0.0, 1.0);
|
||||
truncateToRange (aColor.g(), 0.0, 1.0);
|
||||
truncateToRange (aColor.b(), 0.0, 1.0);
|
||||
}
|
||||
|
||||
const Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
|
||||
if (!aNodalBuilder.IsNull())
|
||||
{
|
||||
aNodalBuilder->SetColor (anElemIter, aQColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
anElemBuilder->SetColor1 (anElemIter, aQColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : FillNodalColorsBuilder
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshDataSource::FillNodalColorsBuilder (const Handle(MeshVS_NodalColorPrsBuilder)& theBuilder) const
|
||||
{
|
||||
if (theBuilder.IsNull()
|
||||
|| !HasNodalColors())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (Standard_Integer aNodeIter = myNodalColors.Lower(); aNodeIter <= myNodalColors.Upper(); ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec4ub& aColor = myNodalColors.Value (aNodeIter);
|
||||
const Quantity_Color aQColor (aColor.r() / 255.0, aColor.g() / 255.0, aColor.b() / 255.0, Quantity_TOC_RGB);
|
||||
theBuilder->SetColor (aNodeIter, aQColor);
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : NbElements
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshDataSource::NbElements (Standard_Integer& theNbTris,
|
||||
Standard_Integer& theNbQuads) const
|
||||
{
|
||||
for (NCollection_Vector<Graphic3d_Vec4i>::Iterator anElemIter (myElements); anElemIter.More(); anElemIter.Next())
|
||||
{
|
||||
const Graphic3d_Vec4i& anElem = anElemIter.Value();
|
||||
if (anElem[3] == -1)
|
||||
{
|
||||
++theNbTris;
|
||||
}
|
||||
else
|
||||
{
|
||||
++theNbQuads;
|
||||
}
|
||||
}
|
||||
}
|
304
src/MeshVS/MeshDataSource.h
Normal file
304
src/MeshVS/MeshDataSource.h
Normal file
@@ -0,0 +1,304 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef MeshDataSource_H
|
||||
#define MeshDataSource_H
|
||||
|
||||
#include <MeshScalarProperty.h>
|
||||
|
||||
#include <MeshVS_DataSource.hxx>
|
||||
#include <MeshVS_EntityType.hxx>
|
||||
#include <MeshVS_ElementalColorPrsBuilder.hxx>
|
||||
#include <MeshVS_NodalColorPrsBuilder.hxx>
|
||||
#include <MeshVS_PrsBuilder.hxx>
|
||||
#include <Message_ProgressIndicator.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <TColStd_HArray2OfInteger.hxx>
|
||||
#include <TColStd_HArray2OfReal.hxx>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define ftell64(a) _ftelli64(a)
|
||||
#define fseek64(a,b,c) _fseeki64(a,b,c)
|
||||
#else
|
||||
#define ftell64(a) ftello(a)
|
||||
#define fseek64(a,b,c) fseeko(a,b,c)
|
||||
#endif
|
||||
|
||||
//! Material definition.
|
||||
struct MeshMaterial
|
||||
{
|
||||
Graphic3d_MaterialAspect Aspect;
|
||||
TCollection_AsciiString Texture;
|
||||
};
|
||||
|
||||
//! Mesh sub-group definition
|
||||
struct MeshGroup
|
||||
{
|
||||
TCollection_AsciiString Name; //!< group name
|
||||
Standard_Integer NodeLower; //!< index of lower Vertex
|
||||
Standard_Integer NodeUpper; //!< index of upper Vertex
|
||||
Standard_Integer ElemLower; //!< index of lower Element
|
||||
Standard_Integer ElemUpper; //!< index of upper Element
|
||||
MeshMaterial Material; //!< associated material
|
||||
|
||||
MeshGroup() : NodeLower (-1), NodeUpper (-1), ElemLower (-1), ElemUpper (-1) {}
|
||||
|
||||
};
|
||||
|
||||
//! The DataSource for working with mesh data.
|
||||
class MeshDataSource : public MeshVS_DataSource
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT MeshDataSource();
|
||||
|
||||
//! Clear mesh structure.
|
||||
Standard_EXPORT void Clear();
|
||||
|
||||
//! Read the mesh from specified file.
|
||||
virtual Standard_Boolean Read (const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& theProgress = NULL,
|
||||
const Standard_Integer theIndexLimit = -1,
|
||||
const Standard_Integer theMemoryLimitMiB = -1) = 0;
|
||||
|
||||
//! Returns geometry information about node or element by co-ordinates.
|
||||
//! For element this method must return all its nodes co-ordinates in the strict order: X, Y, Z and
|
||||
//! with nodes order is the same as in wire bounding the face or link.
|
||||
//! @param theIsElement flag to retrieve information about Element or Node
|
||||
//! @param theNbNodes number of nodes of element, it is recommended to return 1 for node
|
||||
//! @param theType element type
|
||||
Standard_EXPORT virtual Standard_Boolean GetGeom (const Standard_Integer theID,
|
||||
const Standard_Boolean theIsElement,
|
||||
TColStd_Array1OfReal& theCoords,
|
||||
Standard_Integer& theNbNodes,
|
||||
MeshVS_EntityType& theType) const Standard_OVERRIDE;
|
||||
|
||||
//! This method is similar to GetGeom, but returns only element or node type.
|
||||
virtual Standard_Boolean GetGeomType (const Standard_Integer /*theID*/,
|
||||
const Standard_Boolean theIsElement,
|
||||
MeshVS_EntityType& theType) const Standard_OVERRIDE
|
||||
{
|
||||
theType = theIsElement ? MeshVS_ET_Face : MeshVS_ET_Node;
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//! Return pointer which represents element or node data structure.
|
||||
virtual Standard_Address GetAddr (const Standard_Integer /*theID*/,
|
||||
const Standard_Boolean /*theIsElement*/) const Standard_OVERRIDE { return NULL; }
|
||||
|
||||
//! This method returns information about what node this element consist of.
|
||||
Standard_EXPORT virtual Standard_Boolean GetNodesByElement (const Standard_Integer theID,
|
||||
TColStd_Array1OfInteger& theNodeIDs,
|
||||
Standard_Integer& theNbNodes) const Standard_OVERRIDE;
|
||||
|
||||
//! This method returns map of all nodes the object consist of.
|
||||
virtual const TColStd_PackedMapOfInteger& GetAllNodes() const Standard_OVERRIDE { return myFreeNodes; }
|
||||
|
||||
//! This method returns map of all elements the object consist of.
|
||||
virtual const TColStd_PackedMapOfInteger& GetAllElements() const Standard_OVERRIDE { return myUsedElements; }
|
||||
|
||||
//! This method return normal of node ranknode of face Id,
|
||||
//! which is using for smooth shading presentation.
|
||||
//! Returns false if normal isn't defined.
|
||||
Standard_EXPORT virtual Standard_Boolean GetNodeNormal (const Standard_Integer theRankNode,
|
||||
const Standard_Integer theElementId,
|
||||
Standard_Real& theNX,
|
||||
Standard_Real& theNY,
|
||||
Standard_Real& theNZ) const Standard_OVERRIDE;
|
||||
|
||||
public:
|
||||
|
||||
//! Return file comments.
|
||||
const NCollection_Sequence<TCollection_AsciiString>& FileComments() const
|
||||
{
|
||||
return myComments;
|
||||
}
|
||||
|
||||
//! Return list of sub-groups with materials.
|
||||
const NCollection_Vector<MeshGroup>& Groups() { return myGroups; }
|
||||
|
||||
//! Return overall nodes number.
|
||||
Standard_Integer NbNodes() const { return myNodes.Length(); }
|
||||
|
||||
//! Return vector of nodes.
|
||||
const NCollection_Vector<Graphic3d_Vec3>& Nodes() const { return myNodes; }
|
||||
|
||||
//! Return overall elements number.
|
||||
Standard_Integer NbElements() const { return myElements.Length(); }
|
||||
|
||||
//! Determine elements number.
|
||||
Standard_EXPORT void NbElements (Standard_Integer& theNbTris,
|
||||
Standard_Integer& theNbQuads) const;
|
||||
|
||||
//! Return vector of elements.
|
||||
const NCollection_Vector<Graphic3d_Vec4i>& Elements() const { return myElements; }
|
||||
|
||||
//! Return per-node scalar properties.
|
||||
const MeshScalarProperties& NodalQuantities() const { return myNodalQuantities; }
|
||||
|
||||
//! Return per-element scalar properties.
|
||||
const MeshScalarProperties& ElementalQuantities() const { return myElementalQuantities; }
|
||||
|
||||
//! Return true if per-node colors have been assigned
|
||||
Standard_Boolean HasNodalColors() const
|
||||
{
|
||||
return myNodalColors.Length() == myNodes.Length()
|
||||
&& !myNodalColors.IsEmpty();
|
||||
}
|
||||
|
||||
//! Return vector of nodal colors (optional).
|
||||
const NCollection_Vector<Graphic3d_Vec4ub>& NodalColors() const { return myNodalColors; }
|
||||
|
||||
//! Return true if per-node normals have been assigned
|
||||
Standard_Boolean HasNormals() const
|
||||
{
|
||||
return myNormals.Length() == myNodes.Length()
|
||||
&& !myNormals.IsEmpty();
|
||||
}
|
||||
|
||||
//! Return vector of nodal normals (optional).
|
||||
const NCollection_Vector<Graphic3d_Vec3>& Normals() const { return myNormals; }
|
||||
|
||||
//! Return true if per-node UV parameters have been assigned
|
||||
Standard_Boolean HasUV() const
|
||||
{
|
||||
return myNodesUV.Length() == myNodes.Length()
|
||||
&& !myNodesUV.IsEmpty();
|
||||
}
|
||||
|
||||
//! Return vector of nodal UV parameters (optional).
|
||||
const NCollection_Vector<Graphic3d_Vec2>& NodesUV() const { return myNodesUV; }
|
||||
|
||||
//! Return true if texture has been assigned.
|
||||
Standard_Boolean HasTexture() const
|
||||
{
|
||||
Standard_Integer aTextureCount = 0;
|
||||
for (auto anIter = myGroups.cbegin(); anIter != myGroups.cend(); ++anIter)
|
||||
{
|
||||
aTextureCount += (anIter->Material.Texture.IsEmpty()) ? 0 : 1;
|
||||
}
|
||||
return !myGroups.IsEmpty()
|
||||
//&& !myGroups.First().Material.Texture.IsEmpty()
|
||||
&& aTextureCount
|
||||
&& HasUV();
|
||||
}
|
||||
|
||||
//! Return assigned texture.
|
||||
TCollection_AsciiString Texture() const
|
||||
{
|
||||
return HasTexture() ? myGroups.First().Material.Texture : "";
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Fill-in nodal (MeshVS_NodalColorPrsBuilder) or elemental (MeshVS_ElementalColorPrsBuilder) builder.
|
||||
Standard_EXPORT void FillPropertyBuilder (const Handle(MeshVS_PrsBuilder)& theBuilder,
|
||||
const Handle(MeshScalarProperty)& theProperty) const;
|
||||
|
||||
//! Fill-in nodal (MeshVS_NodalColorPrsBuilder) builder by colors.
|
||||
Standard_EXPORT void FillNodalColorsBuilder (const Handle(MeshVS_NodalColorPrsBuilder)& theBuilder) const;
|
||||
|
||||
public:
|
||||
|
||||
//! Append new vertex.
|
||||
void AddNodePosition (const Graphic3d_Vec3& thePosition)
|
||||
{
|
||||
myNodes.Append (thePosition);
|
||||
myUsedNodes.Add (myNodes.Upper());
|
||||
}
|
||||
|
||||
//! Append new vertex.
|
||||
void AddNodePosition (const gp_XYZ& thePosition)
|
||||
{
|
||||
myNodes.Append (Graphic3d_Vec3 ((float )thePosition.X(),
|
||||
(float )thePosition.Y(),
|
||||
(float )thePosition.Z()));
|
||||
myUsedNodes.Add (myNodes.Upper());
|
||||
}
|
||||
|
||||
//! Append new normal.
|
||||
void AddNodeNormal (const Graphic3d_Vec3& theNormal)
|
||||
{
|
||||
myNormals.Append (theNormal);
|
||||
}
|
||||
|
||||
//! Append new normal.
|
||||
void AddNodeNormal (const gp_XYZ& theNormal)
|
||||
{
|
||||
myNormals.Append (Graphic3d_Vec3 ((float )theNormal.X(),
|
||||
(float )theNormal.Y(),
|
||||
(float )theNormal.Z()));
|
||||
}
|
||||
|
||||
//! Append new UV parameters pair.
|
||||
void AddNodeUV (const Graphic3d_Vec2& theUV)
|
||||
{
|
||||
myNodesUV.Append (theUV);
|
||||
}
|
||||
|
||||
//! Append new color.
|
||||
void AddNodeColor (const Graphic3d_Vec4ub& theColor)
|
||||
{
|
||||
myNodalColors.Append (theColor);
|
||||
}
|
||||
|
||||
//! Append node property.
|
||||
void AddNodeProperty (const Standard_Integer thePropIndex,
|
||||
const Standard_Real theValue)
|
||||
{
|
||||
myNodalQuantities.ChangeValue (thePropIndex)->AppendValue (theValue);
|
||||
}
|
||||
|
||||
//! Append new element.
|
||||
void AddElement (const Graphic3d_Vec4i& theNodeIndices)
|
||||
{
|
||||
myElements.Append (theNodeIndices);
|
||||
myUsedElements.Add (myElements.Upper());
|
||||
}
|
||||
|
||||
//! Append element property.
|
||||
void AddElementProperty (const Standard_Integer thePropIndex,
|
||||
const Standard_Real theValue)
|
||||
{
|
||||
myElementalQuantities.ChangeValue (thePropIndex)->AppendValue (theValue);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
TColStd_PackedMapOfInteger myUsedNodes; //!< used node indices
|
||||
TColStd_PackedMapOfInteger myFreeNodes; //!< indices of free nodes
|
||||
TColStd_PackedMapOfInteger myUsedElements; //!< used element indices
|
||||
NCollection_Sequence<TCollection_AsciiString>
|
||||
myComments; //!< file comments
|
||||
NCollection_Vector<Graphic3d_Vec3> myNodes; //!< vector of nodes
|
||||
NCollection_Vector<Graphic3d_Vec3> myNormals; //!< vector of nodal normals (optional)
|
||||
NCollection_Vector<Graphic3d_Vec2> myNodesUV; //!< vector of UV nodes (optional)
|
||||
NCollection_Vector<Graphic3d_Vec4ub> myNodalColors; //!< vector of nodal colors (optional)
|
||||
NCollection_Vector<Graphic3d_Vec4i> myElements; //!< vector of elements
|
||||
MeshScalarProperties myNodalQuantities; //!< per-node scalar quantities
|
||||
MeshScalarProperties myElementalQuantities; //!< per-element scalar quantities
|
||||
|
||||
NCollection_Vector<MeshGroup> myGroups; //!< sub-groups with materials
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(MeshDataSource, MeshVS_DataSource)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(MeshDataSource, MeshVS_DataSource)
|
||||
|
||||
#endif // MeshDataSource_H
|
137
src/MeshVS/MeshPresentation.cpp
Normal file
137
src/MeshVS/MeshPresentation.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#include "MeshPresentation.h"
|
||||
|
||||
#include <MeshVS_Drawer.hxx>
|
||||
#include <MeshVS_DrawerAttribute.hxx>
|
||||
#include <MeshVS_Tool.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(MeshPresentation, MeshVS_Mesh)
|
||||
|
||||
// =======================================================================
|
||||
// function : MeshPresentation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
MeshPresentation::MeshPresentation()
|
||||
{}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetMaterial
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void MeshPresentation::SetMaterial (const Graphic3d_MaterialAspect& theMat)
|
||||
{
|
||||
Handle(MeshVS_Drawer) aDrawer = GetDrawer();
|
||||
if (aDrawer.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aDrawer->SetMaterial (MeshVS_DA_FrontMaterial, theMat);
|
||||
aDrawer->SetMaterial (MeshVS_DA_BackMaterial, theMat);
|
||||
Standard_Boolean hasReflection = Standard_True;
|
||||
aDrawer->GetBoolean (MeshVS_DA_Reflection, hasReflection);
|
||||
Graphic3d_MaterialAspect aMat = theMat;
|
||||
if (!hasReflection)
|
||||
{
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
|
||||
}
|
||||
Handle(Graphic3d_AspectFillArea3d) anAreaAsp = MeshVS_Tool::CreateAspectFillArea3d (aDrawer, aMat);
|
||||
Handle(Graphic3d_AspectLine3d) anOldLineAsp = new Graphic3d_AspectLine3d();
|
||||
Handle(Graphic3d_AspectText3d) anOldTextAsp = new Graphic3d_AspectText3d();
|
||||
Handle(Graphic3d_AspectMarker3d) anOldPntAsp = new Graphic3d_AspectMarker3d();
|
||||
Handle(Graphic3d_AspectFillArea3d) anOldAreaAps = new Graphic3d_AspectFillArea3d();
|
||||
|
||||
const PrsMgr_Presentations& aPrsList = Presentations();
|
||||
for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
|
||||
{
|
||||
const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
|
||||
if (aPrsModed.Mode() == MeshVS_DMF_WireFrame
|
||||
|| aPrsModed.Mode() == MeshVS_DMF_NodalColorDataPrs
|
||||
|| aPrsModed.Mode() == MeshVS_DMF_ElementalColorDataPrs)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
|
||||
for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
|
||||
{
|
||||
const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
|
||||
if (!aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
aGroup->GroupPrimitivesAspect (anOldLineAsp, anOldTextAsp, anOldPntAsp, anOldAreaAps);
|
||||
anAreaAsp->SetTextureMap (anOldAreaAps->TextureMap());
|
||||
if (anOldAreaAps->TextureMapState())
|
||||
{
|
||||
anAreaAsp->SetTextureMapOn();
|
||||
}
|
||||
else
|
||||
{
|
||||
anAreaAsp->SetTextureMapOff();
|
||||
}
|
||||
|
||||
aGroup->SetGroupPrimitivesAspect (anAreaAsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetClosed
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void MeshPresentation::SetClosed (const bool theIsClosed)
|
||||
{
|
||||
const PrsMgr_Presentations& aPrsList = Presentations();
|
||||
for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
|
||||
{
|
||||
const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
|
||||
if (aPrsModed.Mode() == MeshVS_DMF_WireFrame
|
||||
|| aPrsModed.Mode() == MeshVS_DMF_Shrink)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
|
||||
for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
|
||||
{
|
||||
const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
|
||||
if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
|
||||
{
|
||||
aGroup->SetClosed (theIsClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetClosed
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void MeshPresentation::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
|
||||
const Handle(Prs3d_Presentation)& thePrs,
|
||||
const Standard_Integer theMode)
|
||||
{
|
||||
MeshVS_Mesh::Compute (thePrsMgr, thePrs, theMode);
|
||||
|
||||
// mark mesh as closed without checks for Capping algorithm but without suppressing back faces,
|
||||
// thus artifacts on shells will appear only with capping option turned on and not in normal mode
|
||||
SetClosed (true);
|
||||
}
|
57
src/MeshVS/MeshPresentation.h
Normal file
57
src/MeshVS/MeshPresentation.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef MeshPresentation_H
|
||||
#define MeshPresentation_H
|
||||
|
||||
#include <MeshVS_Mesh.hxx>
|
||||
|
||||
//! Interactive presentation for the mesh.
|
||||
class MeshPresentation : public MeshVS_Mesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT MeshPresentation();
|
||||
|
||||
//! Return presentation type.
|
||||
virtual AIS_KindOfInteractive Type() const Standard_OVERRIDE { return AIS_KOI_Object; }
|
||||
|
||||
//! Return presentation signature.
|
||||
virtual Standard_Integer Signature() const Standard_OVERRIDE { return 0; }
|
||||
|
||||
//! Setup new material.
|
||||
virtual void SetMaterial (const Graphic3d_NameOfMaterial theName) Standard_OVERRIDE
|
||||
{
|
||||
SetMaterial (Graphic3d_MaterialAspect (theName));
|
||||
}
|
||||
|
||||
//! Setup new material.
|
||||
virtual void SetMaterial (const Graphic3d_MaterialAspect& theMat) Standard_OVERRIDE;
|
||||
|
||||
//! Override presentation compute.
|
||||
virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
|
||||
const Handle(Prs3d_Presentation)& thePrs,
|
||||
const Standard_Integer theMode) Standard_OVERRIDE;
|
||||
|
||||
//! Setup closed flag.
|
||||
void SetClosed (const bool theIsClosed);
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(MeshPresentation, MeshVS_Mesh)
|
||||
|
||||
};
|
||||
|
||||
#endif // MeshPresentation_H
|
726
src/MeshVS/MeshPrsBuilder.cpp
Normal file
726
src/MeshVS/MeshPrsBuilder.cpp
Normal file
@@ -0,0 +1,726 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifdef __APPLE__
|
||||
#import <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#include "MeshPrsBuilder.h"
|
||||
|
||||
#include <Aspect_TypeOfLine.hxx>
|
||||
#include <MeshVS_Buffer.hxx>
|
||||
#include <MeshVS_DataSource.hxx>
|
||||
#include <MeshVS_Drawer.hxx>
|
||||
#include <MeshVS_DrawerAttribute.hxx>
|
||||
#include <MeshVS_EntityType.hxx>
|
||||
#include <MeshVS_Mesh.hxx>
|
||||
#include <MeshVS_Tool.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Graphic3d_ArrayOfTriangles.hxx>
|
||||
#include <Graphic3d_ArrayOfSegments.hxx>
|
||||
#include <Graphic3d_AspectFillArea3d.hxx>
|
||||
#include <Graphic3d_AspectLine3d.hxx>
|
||||
#include <Graphic3d_Texture2Dmanual.hxx>
|
||||
#include <Image_PixMap.hxx>
|
||||
#include <Prs3d_Drawer.hxx>
|
||||
#include <Prs3d_ShadingAspect.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <TColStd_HArray1OfReal.hxx>
|
||||
#include <TColStd_HPackedMapOfInteger.hxx>
|
||||
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
|
||||
|
||||
static const int THE_NB_COLORS = 128;
|
||||
|
||||
//! Auxiliary wrapper
|
||||
class MeshTexture : public Graphic3d_Texture2Dmanual
|
||||
{
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
MeshTexture (const TCollection_AsciiString& theFileName)
|
||||
: Graphic3d_Texture2Dmanual (theFileName), myPathOrig (theFileName) {}
|
||||
|
||||
//! Image reader.
|
||||
virtual Handle(Image_PixMap) GetImage() const Standard_OVERRIDE
|
||||
{
|
||||
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(__ANDROID__)
|
||||
// mobile version is build without FreeImage to reduce binaries size - use Qt instead
|
||||
Handle(PixMapQt) anImage = new PixMapQt();
|
||||
if(!anImage->Load (myPathOrig))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("Can not read image ") + myPathOrig + "!", Message_Fail);
|
||||
return Handle(Image_PixMap)();
|
||||
}
|
||||
return anImage;
|
||||
#else
|
||||
return Graphic3d_Texture2Dmanual::GetImage();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TCollection_AsciiString myPathOrig;
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(MeshTexture, Graphic3d_Texture2Dmanual)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(MeshTexture, Graphic3d_Texture2Dmanual)
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(MeshPrsTexture, Graphic3d_Texture2D)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(MeshTexture, Graphic3d_Texture2Dmanual)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(MeshPrsBuilder, MeshVS_PrsBuilder)
|
||||
|
||||
//================================================================
|
||||
// Function : MeshPrsBuilder
|
||||
// Purpose :
|
||||
//================================================================
|
||||
MeshPrsBuilder::MeshPrsBuilder (const Handle(MeshVS_Mesh)& theMesh,
|
||||
const MeshVS_DisplayModeFlags& theFlags)
|
||||
: MeshVS_PrsBuilder (theMesh, theFlags, Handle(MeshVS_DataSource)(), -1, MeshVS_BP_NodalColor),
|
||||
myIsElemental (Standard_False),
|
||||
myIsGrayscale (Standard_False),
|
||||
myRangeFrom (0.0),
|
||||
myRangeTo (1.0),
|
||||
myToMapTexture(Standard_False),
|
||||
myToFlipV (Standard_False)
|
||||
{
|
||||
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(__ANDROID__)
|
||||
myToFlipV = Standard_True;
|
||||
#else
|
||||
myToFlipV = Standard_False;
|
||||
#endif
|
||||
|
||||
SetExcluding (Standard_True);
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : buildTextured
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshPrsBuilder::buildTextured (const Handle(Prs3d_Presentation)& thePrs,
|
||||
const TColStd_PackedMapOfInteger& theIDs,
|
||||
TColStd_PackedMapOfInteger& theIDsToExclude) const
|
||||
|
||||
{
|
||||
myPrsGroup.Nullify();
|
||||
|
||||
Handle(MeshDataSource) aSource = Handle(MeshDataSource)::DownCast (GetDataSource());
|
||||
Handle(MeshVS_Drawer) aDrawer = GetDrawer();
|
||||
if (aSource.IsNull()
|
||||
|| aDrawer.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// subtract the hidden elements and ids to exclude (to minimize allocated memory)
|
||||
TColStd_PackedMapOfInteger anIDs;
|
||||
anIDs.Assign (theIDs);
|
||||
Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
|
||||
if (!aHiddenElems.IsNull())
|
||||
{
|
||||
anIDs.Subtract (aHiddenElems->Map());
|
||||
}
|
||||
anIDs.Subtract (theIDsToExclude);
|
||||
|
||||
Standard_Boolean hasReflection = Standard_True;
|
||||
Standard_Boolean isSmoothShading = Standard_False;
|
||||
aDrawer->GetBoolean (MeshVS_DA_Reflection, hasReflection);
|
||||
aDrawer->GetBoolean (MeshVS_DA_SmoothShading, isSmoothShading);
|
||||
|
||||
MeshGroup aFullGroup;
|
||||
aFullGroup.NodeLower = aSource->Nodes().Lower();
|
||||
aFullGroup.NodeUpper = aSource->Nodes().Upper();
|
||||
aFullGroup.ElemLower = aSource->Elements().Lower();
|
||||
aFullGroup.ElemUpper = aSource->Elements().Upper();
|
||||
for (Standard_Integer aGroupIter = 0; aGroupIter == 0 || aGroupIter <= aSource->Groups().Upper(); ++aGroupIter)
|
||||
{
|
||||
const MeshGroup& aGroup = !aSource->Groups().IsEmpty() ? aSource->Groups().Value (aGroupIter) : aFullGroup;
|
||||
const Standard_Integer aNbNodes = aGroup.NodeUpper - aGroup.NodeLower + 1;
|
||||
if (aGroup.NodeLower < 0
|
||||
|| aGroup.NodeUpper < 0
|
||||
|| aGroup.ElemLower < 0
|
||||
|| aGroup.ElemUpper < 0
|
||||
|| aNbNodes < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(MeshTexture) aTexture;
|
||||
if (!aGroup.Material.Texture.IsEmpty()
|
||||
&& myToMapTexture
|
||||
&& aSource->HasUV())
|
||||
{
|
||||
aTexture = new MeshTexture (aGroup.Material.Texture);
|
||||
}
|
||||
|
||||
Standard_Integer aNbTris = 0;
|
||||
for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
|
||||
{
|
||||
if (!anIDs.Contains (anElemIter)) { continue; }
|
||||
const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
|
||||
++aNbTris;
|
||||
if (anElem[3] != -1)
|
||||
{
|
||||
++aNbTris;
|
||||
}
|
||||
}
|
||||
if (aNbTris < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(Graphic3d_ArrayOfTriangles) aTriangles = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3,
|
||||
aSource->HasNormals() || isSmoothShading, Standard_False, !aTexture.IsNull());
|
||||
// fill nodes
|
||||
if (!aTexture.IsNull())
|
||||
{
|
||||
if (aSource->HasNormals())
|
||||
{
|
||||
for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNode = aSource->Nodes() .Value (aNodeIter);
|
||||
const Graphic3d_Vec3& aNorm = aSource->Normals().Value (aNodeIter);
|
||||
const Graphic3d_Vec2& anUV = aSource->NodesUV().Value (aNodeIter);
|
||||
const float aV = myToFlipV ? (1.0f - anUV.y()) : anUV.y();
|
||||
aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z(),
|
||||
aNorm.x(), aNorm.y(), aNorm.z(),
|
||||
anUV.x(), aV);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNode = aSource->Nodes() .Value (aNodeIter);
|
||||
const Graphic3d_Vec2& anUV = aSource->NodesUV().Value (aNodeIter);
|
||||
const float aV = myToFlipV ? (1.0f - anUV.y()) : anUV.y();
|
||||
aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z(),
|
||||
anUV.x(), aV);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aSource->HasNormals())
|
||||
{
|
||||
for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNode = aSource->Nodes() .Value (aNodeIter);
|
||||
const Graphic3d_Vec3& aNorm = aSource->Normals().Value (aNodeIter);
|
||||
aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z(),
|
||||
aNorm.x(), aNorm.y(), aNorm.z());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNode = aSource->Nodes().Value (aNodeIter);
|
||||
aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill indices
|
||||
for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
|
||||
{
|
||||
if (!anIDs.Contains (anElemIter)) { continue; }
|
||||
const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
|
||||
aTriangles->AddEdge (anElem[0] + 1 - aGroup.NodeLower);
|
||||
aTriangles->AddEdge (anElem[1] + 1 - aGroup.NodeLower);
|
||||
aTriangles->AddEdge (anElem[2] + 1 - aGroup.NodeLower);
|
||||
if (anElem[3] != -1)
|
||||
{
|
||||
aTriangles->AddEdge (anElem[0] + 1 - aGroup.NodeLower);
|
||||
aTriangles->AddEdge (anElem[2] + 1 - aGroup.NodeLower);
|
||||
aTriangles->AddEdge (anElem[3] + 1 - aGroup.NodeLower);
|
||||
}
|
||||
}
|
||||
|
||||
// reconstruct normals
|
||||
if (!aSource->HasNormals() && isSmoothShading)
|
||||
{
|
||||
// compute normal at each node, taking into account size of each element (e.g. without pre-normalization)
|
||||
for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
|
||||
{
|
||||
if (!anIDs.Contains (anElemIter)) { continue; }
|
||||
const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
|
||||
|
||||
const Graphic3d_Vec3& aNode0 = aSource->Nodes().Value (anElem[0]);
|
||||
const Graphic3d_Vec3& aNode1 = aSource->Nodes().Value (anElem[1]);
|
||||
const Graphic3d_Vec3& aNode2 = aSource->Nodes().Value (anElem[2]);
|
||||
|
||||
const Graphic3d_Vec3 aVec01 = aNode1 - aNode0;
|
||||
const Graphic3d_Vec3 aVec02 = aNode2 - aNode0;
|
||||
const Graphic3d_Vec3 aCross = Graphic3d_Vec3::Cross (aVec01, aVec02);
|
||||
const Graphic3d_Vec3d aTriNorm (aCross.x(), aCross.y(), aCross.z());
|
||||
const Standard_Integer aNbElemNodes = anElem[3] != -1 ? 4 : 3;
|
||||
Graphic3d_Vec3d aNorm;
|
||||
for (Standard_Integer aNodeIter = 0; aNodeIter < aNbElemNodes; ++aNodeIter)
|
||||
{
|
||||
// Graphic3d_ArrayOfPrimitives zeroes values in costructor
|
||||
const Standard_Integer aNodeIndex = anElem[aNodeIter] + 1 - aGroup.NodeLower;
|
||||
aTriangles->VertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
|
||||
aNorm += aTriNorm;
|
||||
aTriangles->SetVertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
|
||||
}
|
||||
}
|
||||
|
||||
// normalize
|
||||
for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
|
||||
{
|
||||
if (!anIDs.Contains (anElemIter)) { continue; }
|
||||
const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
|
||||
const Standard_Integer aNbElemNodes = anElem[3] != -1 ? 4 : 3;
|
||||
Graphic3d_Vec3d aNorm;
|
||||
for (Standard_Integer aNodeIter = 0; aNodeIter < aNbElemNodes; ++aNodeIter)
|
||||
{
|
||||
const Standard_Integer aNodeIndex = anElem[aNodeIter] + 1 - aGroup.NodeLower;
|
||||
aTriangles->VertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
|
||||
aNorm.Normalize();
|
||||
aTriangles->SetVertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Graphic3d_MaterialAspect aMat[2];
|
||||
aDrawer->GetMaterial(MeshVS_DA_FrontMaterial, aMat[0]);
|
||||
aDrawer->GetMaterial(MeshVS_DA_BackMaterial, aMat[1]);
|
||||
if (aMat[0].Name() == Graphic3d_NOM_DEFAULT
|
||||
&& aGroup.Material.Aspect.Name() != Graphic3d_NOM_DEFAULT)
|
||||
{
|
||||
aMat[0] = aGroup.Material.Aspect;
|
||||
aMat[1] = aGroup.Material.Aspect;
|
||||
}
|
||||
if (!hasReflection)
|
||||
{
|
||||
aMat[0].SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
|
||||
aMat[0].SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
|
||||
aMat[0].SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
|
||||
aMat[0].SetReflectionModeOff (Graphic3d_TOR_EMISSION);
|
||||
}
|
||||
|
||||
Handle(Graphic3d_AspectFillArea3d) anAreaAsp = MeshVS_Tool::CreateAspectFillArea3d (aDrawer, aMat[0]);
|
||||
if (!aTexture.IsNull())
|
||||
{
|
||||
anAreaAsp->SetTextureMap (aTexture);
|
||||
anAreaAsp->SetTextureMapOn();
|
||||
}
|
||||
|
||||
Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup();
|
||||
aPrsGroup->SetGroupPrimitivesAspect (anAreaAsp);
|
||||
aPrsGroup->AddPrimitiveArray (aTriangles);
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : Build
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshPrsBuilder::Build (const Handle(Prs3d_Presentation)& thePrs,
|
||||
const TColStd_PackedMapOfInteger& theIDs,
|
||||
TColStd_PackedMapOfInteger& theIDsToExclude,
|
||||
const Standard_Boolean theIsElement,
|
||||
const Standard_Integer theDisplayMode) const
|
||||
{
|
||||
myPrsGroup.Nullify();
|
||||
if (myProperty.IsNull())
|
||||
{
|
||||
buildTextured (thePrs, theIDs, theIDsToExclude);
|
||||
return;
|
||||
}
|
||||
|
||||
Handle(MeshVS_DataSource) aSource = GetDataSource();
|
||||
Handle(MeshVS_Drawer) aDrawer = GetDrawer();
|
||||
if (aSource.IsNull()
|
||||
|| aDrawer.IsNull()
|
||||
|| myProperty.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Standard_Integer aMaxFaceNodes = 0;
|
||||
if (!aDrawer->GetInteger (MeshVS_DA_MaxFaceNodes, aMaxFaceNodes)
|
||||
|| aMaxFaceNodes <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MeshVS_Buffer aCoordsBuf (3 * aMaxFaceNodes * sizeof(Standard_Real));
|
||||
TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * aMaxFaceNodes);
|
||||
if ((theDisplayMode & GetFlags()) == 0
|
||||
|| !theIsElement)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Standard_Real aLowerValue = propertyLowerValue();
|
||||
const Standard_Real anUpperValue = propertyUpperValue();
|
||||
const Standard_Real aRange = anUpperValue - aLowerValue;
|
||||
|
||||
// subtract the hidden elements and ids to exclude (to minimize allocated memory)
|
||||
TColStd_PackedMapOfInteger anIDs;
|
||||
anIDs.Assign (theIDs);
|
||||
Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
|
||||
if (!aHiddenElems.IsNull())
|
||||
{
|
||||
anIDs.Subtract (aHiddenElems->Map());
|
||||
}
|
||||
anIDs.Subtract (theIDsToExclude);
|
||||
|
||||
Standard_Boolean isReflect = Standard_False, isMeshSmoothShading = Standard_False;
|
||||
aDrawer->GetBoolean (MeshVS_DA_ColorReflection, isReflect);
|
||||
aDrawer->GetBoolean (MeshVS_DA_SmoothShading, isMeshSmoothShading);
|
||||
|
||||
// Following parameter are used for texture presentation only
|
||||
int nbColors = THE_NB_COLORS;///myTextureColorMap.Length(); // Number of colors from color map
|
||||
int nbTextureColors = nbColors; // Number of colors in texture (it will be pow of 2)
|
||||
|
||||
Graphic3d_MaterialAspect aMaterials[2] =
|
||||
{
|
||||
Graphic3d_MaterialAspect (Graphic3d_NOM_PLASTIC),
|
||||
Graphic3d_MaterialAspect (Graphic3d_NOM_PLASTIC)
|
||||
};
|
||||
for (Standard_Integer aMatIter = 0; aMatIter < 2; ++aMatIter)
|
||||
{
|
||||
Graphic3d_MaterialAspect& aMat = aMaterials[aMatIter];
|
||||
if (!isReflect)
|
||||
{
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
|
||||
aMat.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
aMat.SetAmbient (0.5);
|
||||
aMat.SetDiffuse (0.5);
|
||||
aMat.SetSpecular(0.0);
|
||||
aMat.SetEmissive(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Integer aNbFacePrimitives = 0;
|
||||
Standard_Integer aNbEdgePrimitives = 0;
|
||||
for (TColStd_MapIteratorOfPackedMapOfInteger it (anIDs); it.More(); it.Next())
|
||||
{
|
||||
MeshVS_EntityType aType = MeshVS_ET_NONE;
|
||||
Standard_Integer aNbNodes = 0;
|
||||
if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)
|
||||
|| aType != MeshVS_ET_Face)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
aNbEdgePrimitives += aNbNodes; // add edge segments
|
||||
aNbFacePrimitives += aNbNodes - 2; // add face triangles
|
||||
}
|
||||
|
||||
Standard_Boolean toShowEdges = Standard_True;
|
||||
aDrawer->GetBoolean (MeshVS_DA_ShowEdges, toShowEdges);
|
||||
|
||||
// Here we do not use indices arrays because they are not effective for some mesh
|
||||
// drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
|
||||
// cell rendering (normal interpolation is not always applicable - flat shading),
|
||||
// elemental coloring (color interpolation is impossible)
|
||||
|
||||
Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles (aNbFacePrimitives * 3, 0,
|
||||
Standard_True, Standard_False, Standard_True);
|
||||
Handle(Graphic3d_ArrayOfSegments) anEdgeSegments;
|
||||
if (toShowEdges)
|
||||
{
|
||||
anEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
|
||||
}
|
||||
|
||||
gp_Pnt P, Start;
|
||||
Standard_Real aMin = gp::Resolution() * gp::Resolution();
|
||||
gp_Dir aDefNorm = gp::DZ();
|
||||
|
||||
TColStd_Array1OfInteger aNodes (1, 10);
|
||||
for (TColStd_MapIteratorOfPackedMapOfInteger it (anIDs); it.More(); it.Next())
|
||||
{
|
||||
Standard_Integer aKey = it.Key();
|
||||
Standard_Integer aNbNodes = 0;
|
||||
MeshVS_EntityType aType = MeshVS_ET_NONE;
|
||||
if (!aSource->GetGeom (aKey, Standard_True, aCoords, aNbNodes, aType)
|
||||
|| aType != MeshVS_ET_Face
|
||||
|| aNbNodes > 10
|
||||
|| !aSource->GetNodesByElement (aKey, aNodes, aNbNodes))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Preparing normal(s) to show reflections if requested
|
||||
Handle(TColStd_HArray1OfReal) aNormals;
|
||||
Standard_Boolean hasNormals = isReflect
|
||||
&& aSource->GetNormalsByElement (aKey, isMeshSmoothShading, aMaxFaceNodes, aNormals);
|
||||
|
||||
for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbNodes - 2; ++aNodeIdx)
|
||||
{
|
||||
for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx)
|
||||
{
|
||||
gp_XYZ aPnt (aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
|
||||
aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
|
||||
aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
|
||||
|
||||
gp_Vec aNorm = aDefNorm;
|
||||
if (hasNormals)
|
||||
{
|
||||
gp_Vec aTestNorm (aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
|
||||
aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
|
||||
aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
|
||||
|
||||
if (aTestNorm.SquareMagnitude() > aMin)
|
||||
{
|
||||
aNorm = gp_Dir (aTestNorm);
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve nodal value
|
||||
Standard_Integer aNodeIndex = aKey;
|
||||
if (!myIsElemental)
|
||||
{
|
||||
aNodeIndex = aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1));
|
||||
}
|
||||
|
||||
Standard_Real aTexCoordU = 0.25;
|
||||
Standard_Real aTexCoordV = 0.25;
|
||||
const Standard_Real aValue = myProperty->Value (aNodeIndex);
|
||||
if (aRange > gp::Resolution()
|
||||
&& !IsNaN (aValue))
|
||||
{
|
||||
const Standard_Real aNormVal = (aValue - aLowerValue) / aRange;
|
||||
aTexCoordU = (aNormVal * (nbColors - 1.0) + 0.5) / nbTextureColors;
|
||||
aTexCoordV = 0.75;
|
||||
}
|
||||
|
||||
// Transform texture coordinate in accordance with number of colors specified
|
||||
// by upper level and real size of OpenGL texture. The OpenGL texture has border
|
||||
// colors interpolated with the colors from the color map, thats why we need to
|
||||
// shrink texture coordinates around the middle point to exclude areas where the
|
||||
// map colors are interpolated with the borders color
|
||||
aFaceTriangles->AddVertex (aPnt, aNorm, gp_Pnt2d (aTexCoordU, aTexCoordV));
|
||||
}
|
||||
}
|
||||
|
||||
if (!anEdgeSegments.IsNull())
|
||||
{
|
||||
for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbNodes; ++aNodeIdx) // border segmentation
|
||||
{
|
||||
const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
|
||||
|
||||
anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
|
||||
aCoords (3 * aNodeIdx + 2),
|
||||
aCoords (3 * aNodeIdx + 3));
|
||||
|
||||
anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
|
||||
aCoords (3 * aNextIdx + 2),
|
||||
aCoords (3 * aNextIdx + 3));
|
||||
}
|
||||
}
|
||||
|
||||
// if IsExcludingOn then presentation must not be built by other builders
|
||||
if (IsExcludingOn())
|
||||
{
|
||||
theIDsToExclude.Add (aKey);
|
||||
}
|
||||
}
|
||||
|
||||
Aspect_TypeOfLine anEdgeType = Aspect_TOL_SOLID;
|
||||
Standard_Integer anEdgeInt;
|
||||
Standard_Real anEdgeWidth;
|
||||
Quantity_Color anInteriorColor, anEdgeColor, aLineColor;
|
||||
|
||||
aDrawer->GetColor (MeshVS_DA_InteriorColor, anInteriorColor);
|
||||
aDrawer->GetColor (MeshVS_DA_EdgeColor, anEdgeColor);
|
||||
aDrawer->GetColor (MeshVS_DA_BeamColor, aLineColor);
|
||||
aDrawer->GetDouble (MeshVS_DA_EdgeWidth, anEdgeWidth);
|
||||
|
||||
if (aDrawer->GetInteger (MeshVS_DA_EdgeType, anEdgeInt))
|
||||
{
|
||||
anEdgeType = (Aspect_TypeOfLine )anEdgeInt;
|
||||
}
|
||||
|
||||
Handle(Prs3d_Drawer) aPrs3dDrawer = myParentMesh->Attributes();
|
||||
if (aPrs3dDrawer.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aPrs3dDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
|
||||
|
||||
myFillAsp = new Graphic3d_AspectFillArea3d();
|
||||
*myFillAsp = *aPrs3dDrawer->ShadingAspect()->Aspect();
|
||||
|
||||
myFillAsp->SetFrontMaterial(aMaterials[0]);
|
||||
myFillAsp->SetBackMaterial (aMaterials[1]);
|
||||
|
||||
Handle(Graphic3d_Texture2D) aTexture = createTexture (myIsGrayscale, myRangeFrom, myRangeTo, myProperty->IsInversed());
|
||||
if (aTexture.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myFillAsp->SetTextureMapOn();
|
||||
myFillAsp->SetTextureMap (aTexture);
|
||||
myFillAsp->SetInteriorColor (Quantity_NOC_WHITE);
|
||||
|
||||
myFillAsp->SetDistinguishOff();
|
||||
myFillAsp->SetEdgeOff();
|
||||
|
||||
Handle(Graphic3d_Group) aGroup1 = thePrs->NewGroup();
|
||||
aGroup1->SetGroupPrimitivesAspect (myFillAsp);
|
||||
aGroup1->AddPrimitiveArray (aFaceTriangles);
|
||||
|
||||
myPrsGroup = aGroup1;
|
||||
|
||||
if (toShowEdges)
|
||||
{
|
||||
Handle(Graphic3d_Group) aGroup2 = thePrs->NewGroup();
|
||||
|
||||
Handle(Graphic3d_AspectLine3d) anLAsp = new Graphic3d_AspectLine3d (anEdgeColor, anEdgeType, anEdgeWidth);
|
||||
aGroup2->SetGroupPrimitivesAspect (anLAsp);
|
||||
aGroup2->AddPrimitiveArray (anEdgeSegments);
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : SetProperty
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshPrsBuilder::SetProperty (const Handle(MeshScalarProperty)& theProperty,
|
||||
const Standard_Boolean theIsElemental)
|
||||
{
|
||||
myProperty = theProperty;
|
||||
myIsElemental = theIsElemental;
|
||||
if (!myProperty.IsNull())
|
||||
{
|
||||
myRangeFrom = myProperty->ColorscaleRangeFrom();
|
||||
myRangeTo = myProperty->ColorscaleRangeTo();
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : SetRange
|
||||
// Purpose :
|
||||
//================================================================
|
||||
void MeshPrsBuilder::SetRange (const Standard_Real theFrom,
|
||||
const Standard_Real theTo,
|
||||
const bool theIsInversed)
|
||||
{
|
||||
Standard_Real aPrec = 1.0 / Standard_Real(THE_NB_COLORS * 10);
|
||||
if (Abs (myRangeFrom - theFrom) < aPrec
|
||||
&& Abs (myRangeTo - theTo) < aPrec
|
||||
&& (myProperty.IsNull() || myProperty->IsInversed() == theIsInversed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myRangeFrom = theFrom;
|
||||
myRangeTo = theTo;
|
||||
if (!myProperty.IsNull())
|
||||
{
|
||||
myProperty->SetInversed (theIsInversed);
|
||||
myProperty->SetColorscaleRange (theFrom, theTo);
|
||||
}
|
||||
if (myPrsGroup.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Handle(Graphic3d_Texture2D) aTexture = createTexture (myIsGrayscale, myRangeFrom, myRangeTo, theIsInversed);
|
||||
if (aTexture.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myFillAsp->SetTextureMap (aTexture);
|
||||
myPrsGroup->SetGroupPrimitivesAspect (myFillAsp);
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : createTexture
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Handle(Graphic3d_Texture2D) MeshPrsBuilder::createTexture (const Standard_Boolean theIsGrayscale,
|
||||
const Standard_Real theFrom,
|
||||
const Standard_Real theTo,
|
||||
const bool theIsInversed)
|
||||
{
|
||||
const Standard_Integer aNbColors = THE_NB_COLORS;
|
||||
|
||||
const Graphic3d_Vec3d anOut = Graphic3d_Vec3d (0.5, 0.5, 0.5);
|
||||
Graphic3d_Vec3d aScale00 = theIsGrayscale ? Graphic3d_Vec3d (0.0, 0.0, 0.0) : Graphic3d_Vec3d (0.0, 0.0, 1.0);
|
||||
Graphic3d_Vec3d aScale05 = theIsGrayscale ? Graphic3d_Vec3d (0.5, 0.5, 0.5) : Graphic3d_Vec3d (0.0, 1.0, 0.0);
|
||||
Graphic3d_Vec3d aScale10 = theIsGrayscale ? Graphic3d_Vec3d (1.0, 1.0, 1.0) : Graphic3d_Vec3d (1.0, 0.0, 0.0);
|
||||
if (theIsInversed)
|
||||
{
|
||||
std::swap (aScale00, aScale10);
|
||||
}
|
||||
|
||||
const Standard_Real aRange = Max (theTo - theFrom, 0.01);
|
||||
const Standard_Real aRangeInv = 1.0 / aRange;
|
||||
const Standard_Real aMiddle = theFrom + 0.5 * aRange;
|
||||
const Standard_Real aFrom = theFrom;
|
||||
|
||||
// create and fill image with colors
|
||||
Handle(Image_PixMap) anImage = new Image_PixMap();
|
||||
if (!anImage->InitTrash (Image_PixMap::ImgRGBA, aNbColors, 2))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Image_ColorRGBA anOutColor;
|
||||
anOutColor.r() = Standard_Byte(255.0 * anOut.r());
|
||||
anOutColor.g() = Standard_Byte(255.0 * anOut.g());
|
||||
anOutColor.b() = Standard_Byte(255.0 * anOut.b());
|
||||
anOutColor.a() = 0xFF;
|
||||
|
||||
anImage->SetTopDown (false);
|
||||
for (Standard_Size aColIter = 0; aColIter < Standard_Size(aNbColors); ++aColIter)
|
||||
{
|
||||
const Standard_Real aValue = Standard_Real(aColIter) / Standard_Real(aNbColors - 1);
|
||||
Graphic3d_Vec3d aColorVal;
|
||||
if (aValue < theFrom
|
||||
|| aValue > theTo)
|
||||
{
|
||||
aColorVal = anOut;
|
||||
}
|
||||
else if (aValue < aMiddle)
|
||||
{
|
||||
const Standard_Real aHalfVal = (aValue - aFrom) * 2.0 * aRangeInv;
|
||||
aColorVal = aScale00 * (1.0 - aHalfVal) + aScale05 * aHalfVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Standard_Real aHalfVal = (aValue - aFrom) * 2.0 * aRangeInv - 1.0;
|
||||
aColorVal = aScale05 * (1.0 - aHalfVal) + aScale10 * aHalfVal;
|
||||
}
|
||||
|
||||
Image_ColorRGBA& aColor0 = anImage->ChangeValue<Image_ColorRGBA> (0, aColIter);
|
||||
Image_ColorRGBA& aColor1 = anImage->ChangeValue<Image_ColorRGBA> (1, aColIter);
|
||||
aColor0.r() = Standard_Byte(255.0 * aColorVal.r());
|
||||
aColor0.g() = Standard_Byte(255.0 * aColorVal.g());
|
||||
aColor0.b() = Standard_Byte(255.0 * aColorVal.b());
|
||||
aColor0.a() = 0xFF;
|
||||
aColor1 = anOutColor;
|
||||
}
|
||||
|
||||
// create texture
|
||||
return new MeshPrsTexture (anImage);
|
||||
}
|
147
src/MeshVS/MeshPrsBuilder.h
Normal file
147
src/MeshVS/MeshPrsBuilder.h
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef MeshPrsBuilder_H
|
||||
#define MeshPrsBuilder_H
|
||||
|
||||
#include "MeshDataSource.h"
|
||||
|
||||
#include <MeshVS_PrsBuilder.hxx>
|
||||
#include <Graphic3d_Texture2D.hxx>
|
||||
#include <Graphic3d_TextureParams.hxx>
|
||||
|
||||
//! Auxiliary class to hold texture.
|
||||
class MeshPrsTexture : public Graphic3d_Texture2D
|
||||
{
|
||||
public:
|
||||
|
||||
MeshPrsTexture (const Handle(Image_PixMap)& theImg)
|
||||
: Graphic3d_Texture2D (theImg, Graphic3d_TOT_2D)
|
||||
{
|
||||
myParams->SetModulate (Standard_True);
|
||||
myParams->SetFilter (Graphic3d_TOTF_BILINEAR);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(MeshPrsTexture, Graphic3d_Texture2D)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(MeshPrsTexture, Graphic3d_Texture2D)
|
||||
|
||||
//! Auxiliary builder for Nodal or Elemental mesh properties using textured colorscale.
|
||||
class MeshPrsBuilder : public MeshVS_PrsBuilder
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor.
|
||||
Standard_EXPORT MeshPrsBuilder (const Handle(MeshVS_Mesh)& theMesh,
|
||||
const MeshVS_DisplayModeFlags& theFlags);
|
||||
|
||||
//! Setup textures when available.
|
||||
Standard_Boolean ToMapTextures() const { return myToMapTexture; }
|
||||
|
||||
//! Setup textures when available.
|
||||
void SetMapTextures (const Standard_Boolean theToMap) { myToMapTexture = theToMap; }
|
||||
|
||||
public:
|
||||
|
||||
//! Setup property to display.
|
||||
Standard_EXPORT void SetProperty (const Handle(MeshScalarProperty)& theProperty,
|
||||
const Standard_Boolean theIsElemental);
|
||||
|
||||
//! Grayscale flag.
|
||||
Standard_Boolean IsGrayscale() const
|
||||
{
|
||||
return myIsGrayscale;
|
||||
}
|
||||
|
||||
//! Specify using grayscale or B->G->R colorscale
|
||||
void SetGrayscale (const Standard_Boolean theIsGrayscale)
|
||||
{
|
||||
myIsGrayscale = theIsGrayscale;
|
||||
}
|
||||
|
||||
//! Adjust colorscale range.
|
||||
Standard_EXPORT void SetRange (const Standard_Real theFrom,
|
||||
const Standard_Real theTo,
|
||||
const bool theIsInversed);
|
||||
|
||||
public:
|
||||
|
||||
//! Main builder.
|
||||
Standard_EXPORT virtual void Build (const Handle(Prs3d_Presentation)& thePrs,
|
||||
const TColStd_PackedMapOfInteger& theIDs,
|
||||
TColStd_PackedMapOfInteger& theIDsToExclude,
|
||||
const Standard_Boolean theIsElement,
|
||||
const Standard_Integer theDisplayMode) const Standard_OVERRIDE;
|
||||
|
||||
protected:
|
||||
|
||||
//! Textured presentation builder.
|
||||
void buildTextured (const Handle(Prs3d_Presentation)& thePrs,
|
||||
const TColStd_PackedMapOfInteger& theIDs,
|
||||
TColStd_PackedMapOfInteger& theIDsToExclude) const;
|
||||
|
||||
//! Auxiliary method to create texture.
|
||||
static Handle(Graphic3d_Texture2D) createTexture (const Standard_Boolean theIsGrayscale,
|
||||
const Standard_Real theFrom,
|
||||
const Standard_Real theTo,
|
||||
const bool theIsInversed);
|
||||
|
||||
//! Return lower property value.
|
||||
Standard_Real propertyLowerValue() const
|
||||
{
|
||||
if (myProperty.IsNull())
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
return myIsGrayscale ? Min (0.0, myProperty->LowerValue()) : myProperty->LowerValue();
|
||||
}
|
||||
|
||||
//! Return upper property value.
|
||||
Standard_Real propertyUpperValue() const
|
||||
{
|
||||
if (myProperty.IsNull())
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
return myIsGrayscale ? Max (1.0, myProperty->UpperValue()) : myProperty->UpperValue();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Handle(MeshScalarProperty) myProperty; //!< property to display
|
||||
Standard_Boolean myIsElemental; //!< flag indicating elemental property
|
||||
Standard_Boolean myIsGrayscale; //!< flag to create grayscale colorscale
|
||||
Standard_Real myRangeFrom; //!< colorscale range, lower value
|
||||
Standard_Real myRangeTo; //!< colorscale range, upper value
|
||||
|
||||
Standard_Boolean myToMapTexture;//!< setup textures when available
|
||||
Standard_Boolean myToFlipV; //!< flip texture coordinates vertically
|
||||
|
||||
mutable Handle(Graphic3d_Group) myPrsGroup; //!< presentation group with triangles
|
||||
mutable Handle(Graphic3d_AspectFillArea3d) myFillAsp;
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(MeshPrsBuilder, MeshVS_PrsBuilder)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(MeshPrsBuilder, MeshVS_PrsBuilder)
|
||||
|
||||
#endif // MeshPrsBuilder_H
|
124
src/MeshVS/MeshScalarProperty.h
Normal file
124
src/MeshVS/MeshScalarProperty.h
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef MeshScalarProperty_H
|
||||
#define MeshScalarProperty_H
|
||||
|
||||
#include <gp_XYZ.hxx>
|
||||
#include <Graphic3d_Vec.hxx>
|
||||
#include <NCollection_Vector.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
//! Return true for NaN.
|
||||
inline bool IsNaN (const double theValue)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return ::_isnan (theValue) != 0;
|
||||
#else
|
||||
return std::isnan (theValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Property assigned to Mesh elements or nodes
|
||||
class MeshScalarProperty : public Standard_Transient
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Return property name.
|
||||
const TCollection_AsciiString& Name() const { return myName; }
|
||||
|
||||
//! Return lower index.
|
||||
Standard_Integer LowerIndex() const { return myValues.Lower(); }
|
||||
|
||||
//! Return upper index.
|
||||
Standard_Integer UpperIndex() const { return myValues.Upper(); }
|
||||
|
||||
//! Return value for specified index.
|
||||
Standard_Real Value (const Standard_Integer theIndex) const { return myValues.Value (theIndex); }
|
||||
|
||||
//! Return lower value of the property.
|
||||
Standard_Real LowerValue() const { return myValueLower; }
|
||||
|
||||
//! Return lower value of the property.
|
||||
Standard_Real UpperValue() const { return myValueUpper; }
|
||||
|
||||
//! Return true if values has opposite meaning (greater value is better).
|
||||
bool IsInversed() const { return myIsInversed; }
|
||||
|
||||
//! Setup flag inficating that values has opposite meaning (greater value is better) or normal meaning (greater value is badder).
|
||||
void SetInversed(const bool theIsInversed) { myIsInversed = theIsInversed; }
|
||||
|
||||
//! Return colorscale range (from).
|
||||
Standard_Real ColorscaleRangeFrom() const { return myCSRangeFrom; }
|
||||
|
||||
//! Return colorscale range (to).
|
||||
Standard_Real ColorscaleRangeTo() const { return myCSRangeTo; }
|
||||
|
||||
//! Setup colorscale range.
|
||||
void SetColorscaleRange (const Standard_Real theFrom,
|
||||
const Standard_Real theTo)
|
||||
{
|
||||
myCSRangeFrom = theFrom;
|
||||
myCSRangeTo = theTo;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor.
|
||||
MeshScalarProperty (const TCollection_AsciiString& theName)
|
||||
: myName (theName),
|
||||
myValueLower ( Precision::Infinite()),
|
||||
myValueUpper (-Precision::Infinite()),
|
||||
myCSRangeFrom(0.0),
|
||||
myCSRangeTo (1.0),
|
||||
myIsInversed (false)
|
||||
{}
|
||||
|
||||
//! Append new value
|
||||
void AppendValue (const Standard_Real theValue)
|
||||
{
|
||||
myValues.Append ((float )theValue);
|
||||
|
||||
if (!IsNaN (theValue))
|
||||
{
|
||||
myValueLower = Min (myValueLower, theValue);
|
||||
myValueUpper = Max (myValueUpper, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
TCollection_AsciiString myName; //!< property name
|
||||
//NCollection_Vector<Standard_Real> myValues; //!< property values
|
||||
NCollection_Vector<float> myValues; //!< property values
|
||||
Standard_Real myValueLower; //!< values range - lower value
|
||||
Standard_Real myValueUpper; //!< values range - upper value
|
||||
Standard_Real myCSRangeFrom;//!< colorscale range - from
|
||||
Standard_Real myCSRangeTo; //!< colorscale range - to
|
||||
bool myIsInversed; //!< values meaning
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(MeshScalarProperty, Standard_Transient)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(MeshScalarProperty, Standard_Transient)
|
||||
|
||||
typedef NCollection_Vector<Handle(MeshScalarProperty)> MeshScalarProperties;
|
||||
|
||||
#endif // MeshScalarProperty_H
|
680
src/MeshVS/ObjDataSource.cpp
Normal file
680
src/MeshVS/ObjDataSource.cpp
Normal file
@@ -0,0 +1,680 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <ObjDataSource.h>
|
||||
|
||||
#include <Standard_CLocaleSentry.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Message_ProgressSentry.hxx>
|
||||
#include <OSD_OpenFile.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
#include <Quantity_Color.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(ObjDataSource, MeshDataSource)
|
||||
|
||||
//! Simple wrapper.
|
||||
struct FileSentry
|
||||
{
|
||||
FILE* File;
|
||||
|
||||
FileSentry (const TCollection_AsciiString& theFile)
|
||||
: File (OSD_OpenFile (theFile.ToCString(), "rb")) {}
|
||||
|
||||
~FileSentry()
|
||||
{
|
||||
if (File != NULL)
|
||||
{
|
||||
::fclose (File);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//! Read 3 float values.
|
||||
inline bool objReadVec3 (const char* thePos,
|
||||
char*& theNext,
|
||||
Graphic3d_Vec3& theVec)
|
||||
{
|
||||
const char* aPos = thePos;
|
||||
theVec.x() = (float )Strtod (aPos, &theNext);
|
||||
aPos = theNext;
|
||||
theVec.y() = (float )Strtod (aPos, &theNext);
|
||||
aPos = theNext;
|
||||
theVec.z() = (float )Strtod (aPos, &theNext);
|
||||
return aPos != theNext;
|
||||
}
|
||||
|
||||
//! Read string.
|
||||
inline bool objReadName (const char* thePos,
|
||||
TCollection_AsciiString& theName)
|
||||
{
|
||||
TCollection_AsciiString aName = TCollection_AsciiString (thePos);
|
||||
Standard_Integer aTail = aName.Length();
|
||||
if (aTail > 0
|
||||
&& aName.Value (aTail) == '\n')
|
||||
{
|
||||
aName.SetValue (aTail--, '\0'); // replace '\n'
|
||||
}
|
||||
if (aTail > 0
|
||||
&& aName.Value (aTail) == '\r')
|
||||
{
|
||||
aName.SetValue (aTail--, '\0'); // replace '\r'
|
||||
}
|
||||
theName = aName.ToCString();
|
||||
theName.LeftAdjust();
|
||||
theName.RightAdjust();
|
||||
return !theName.IsEmpty();
|
||||
}
|
||||
|
||||
//! Reader of mtl files.
|
||||
class ObjMaterialReader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
ObjMaterialReader (NCollection_DataMap<TCollection_AsciiString, MeshMaterial>& theMaterials)
|
||||
: myFile (NULL), myMaterials (&theMaterials), myNbLines (0) {}
|
||||
|
||||
//! Destructor.
|
||||
~ObjMaterialReader()
|
||||
{
|
||||
if (myFile != NULL)
|
||||
{
|
||||
::fclose (myFile);
|
||||
}
|
||||
}
|
||||
|
||||
//! Read the file.
|
||||
Standard_Boolean Read (const TCollection_AsciiString& theFolder,
|
||||
const TCollection_AsciiString& theFile)
|
||||
{
|
||||
myPath = theFolder + theFile;
|
||||
myFile = OSD_OpenFile (myPath.ToCString(), "rb");
|
||||
if (myFile == NULL)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("OBJ material file '") + myPath + "' is not found!", Message_Warning);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
char aLine[256] = {};
|
||||
TCollection_AsciiString aMatName;
|
||||
MeshMaterial aMat;
|
||||
const Standard_Integer aNbMatOld = myMaterials->Extent();
|
||||
bool hasAspect = false;
|
||||
for (; ::feof (myFile) == 0 && ::fgets (aLine, 255, myFile) != NULL; )
|
||||
{
|
||||
++myNbLines;
|
||||
|
||||
const char* aPos = aLine;
|
||||
if (*aLine == '#'
|
||||
|| *aLine == '\n'
|
||||
|| *aLine == '\0')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (::memcmp (aLine, "newmtl ", 7) == 0)
|
||||
{
|
||||
aPos += 7;
|
||||
if (!aMatName.IsEmpty())
|
||||
{
|
||||
if (hasAspect)
|
||||
{
|
||||
aMat.Aspect.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
|
||||
aMat.Aspect.SetMaterialName (aMatName.ToCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset incomplete material definition
|
||||
aMat.Aspect = Graphic3d_MaterialAspect();
|
||||
}
|
||||
myMaterials->Bind (aMatName, aMat);
|
||||
hasAspect = false;
|
||||
}
|
||||
|
||||
aMatName = TCollection_AsciiString(aPos);
|
||||
aMat = MeshMaterial();
|
||||
if (!objReadName (aPos, aMatName))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Empty OBJ material at line ") + myNbLines + " in file " + myPath, Message_Warning);
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "Ka ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Graphic3d_Vec3 aColor;
|
||||
objReadVec3 (aPos, aNext, aColor);
|
||||
aPos = aNext;
|
||||
if (validateColor (aColor))
|
||||
{
|
||||
Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
|
||||
aMat.Aspect.SetAmbientColor (aQColor);
|
||||
hasAspect = true;
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "Kd ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Graphic3d_Vec3 aColor;
|
||||
objReadVec3 (aPos, aNext, aColor);
|
||||
aPos = aNext;
|
||||
if (validateColor (aColor))
|
||||
{
|
||||
Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
|
||||
aMat.Aspect.SetDiffuseColor (aQColor);
|
||||
hasAspect = true;
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "Ks ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Graphic3d_Vec3 aColor;
|
||||
objReadVec3 (aPos, aNext, aColor);
|
||||
aPos = aNext;
|
||||
if (validateColor (aColor))
|
||||
{
|
||||
Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
|
||||
aMat.Aspect.SetSpecularColor (aQColor);
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "Ns ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Standard_Real aSpecular = Strtod (aPos, &aNext);
|
||||
aPos = aNext;
|
||||
if (aSpecular >= 0.0
|
||||
&& aSpecular <= 128.0)
|
||||
{
|
||||
aMat.Aspect.SetShininess (aSpecular / 128.0);
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "Tr ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Standard_Real anAlpha = Strtod (aPos, &aNext);
|
||||
aPos = aNext;
|
||||
if (validateScalar (anAlpha))
|
||||
{
|
||||
//aMat.Aspect.SetTransparency (anAlpha);
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "map_Kd ", 7) == 0)
|
||||
{
|
||||
aPos += 7;
|
||||
if (!objReadName (aPos, aMat.Texture))
|
||||
{
|
||||
//
|
||||
}
|
||||
else
|
||||
{
|
||||
aMat.Texture = theFolder + aMat.Texture;
|
||||
}
|
||||
}
|
||||
/*else if (::memcmp (aLine, "illum ", 6) == 0)
|
||||
{
|
||||
aPos += 6;
|
||||
char* aNext = NULL;
|
||||
const int aModel = strtol (aPos, &aNext, 10);
|
||||
aPos = aNext;
|
||||
if (aModel < 0 || aModel > 10)
|
||||
{
|
||||
// unknown model
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (!aMatName.IsEmpty())
|
||||
{
|
||||
if (hasAspect)
|
||||
{
|
||||
aMat.Aspect.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
|
||||
aMat.Aspect.SetMaterialName (aMatName.ToCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset incomplete material definition
|
||||
aMat.Aspect = Graphic3d_MaterialAspect();
|
||||
}
|
||||
myMaterials->Bind (aMatName, aMat);
|
||||
}
|
||||
return myMaterials->Extent() != aNbMatOld;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//! Validate scalar value
|
||||
inline bool validateScalar (const Standard_Real theValue)
|
||||
{
|
||||
if (theValue < 0.0
|
||||
|| theValue > 1.0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid scalar in OBJ material at line ") + myNbLines + " in file " + myPath, Message_Warning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Validate RGB color
|
||||
inline bool validateColor (const Graphic3d_Vec3& theVec)
|
||||
{
|
||||
if (theVec.r() < 0.0 || theVec.r() > 1.0
|
||||
|| theVec.g() < 0.0 || theVec.g() > 1.0
|
||||
|| theVec.b() < 0.0 || theVec.b() > 1.0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid color in OBJ material at line ") + myNbLines + " in file " + myPath, Message_Warning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
FILE* myFile;
|
||||
TCollection_AsciiString myPath;
|
||||
NCollection_DataMap<TCollection_AsciiString, MeshMaterial>* myMaterials;
|
||||
Standard_Integer myNbLines;
|
||||
|
||||
};
|
||||
|
||||
//================================================================
|
||||
// Function : Constructor
|
||||
// Purpose :
|
||||
//================================================================
|
||||
ObjDataSource::ObjDataSource()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//! Hasher for 3 ordered integers.
|
||||
class ObjVec3iHasher
|
||||
{
|
||||
public:
|
||||
|
||||
static Standard_Integer HashCode (const Graphic3d_Vec3i& theKey,
|
||||
const Standard_Integer theUpper)
|
||||
{
|
||||
return ::HashCode (::HashCodes ((Standard_CString )&theKey, sizeof(Graphic3d_Vec3i)), theUpper);
|
||||
}
|
||||
|
||||
static Standard_Boolean IsEqual (const Graphic3d_Vec3i& theKey1,
|
||||
const Graphic3d_Vec3i& theKey2)
|
||||
{
|
||||
return theKey1[0] == theKey2[0]
|
||||
&& theKey1[1] == theKey2[1]
|
||||
&& theKey1[2] == theKey2[2];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//================================================================
|
||||
// Function : Read
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Standard_Boolean ObjDataSource::Read (const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& theProgress,
|
||||
const Standard_Integer /*theIndexLimit*/,
|
||||
const Standard_Integer theMemLimitMiB)
|
||||
{
|
||||
Clear();
|
||||
|
||||
Standard_CLocaleSentry aLocaleSentry;
|
||||
FileSentry aFile (theFile);
|
||||
if (aFile.File == NULL)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("File '") + theFile + "' is not found!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// determine file location to load associated files
|
||||
TCollection_AsciiString aFolder;
|
||||
{
|
||||
OSD_Path aPath (theFile);
|
||||
aPath.SetName ("");
|
||||
aPath.SetExtension ("");
|
||||
aPath.SystemName (aFolder);
|
||||
}
|
||||
|
||||
// determine length of file
|
||||
::fseek64 (aFile.File, 0, SEEK_END);
|
||||
const int64_t aFileLen = ::ftell64 (aFile.File);
|
||||
if (aFileLen <= 0L)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("File '") + theFile + "' is empty!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
::fseek64 (aFile.File, 0, SEEK_SET);
|
||||
|
||||
const Standard_Integer aNbMiBTotal = Standard_Integer(aFileLen / (1024 * 1024));
|
||||
Standard_Integer aNbMiBPassed = 0;
|
||||
Message_ProgressSentry aPSentry (theProgress, "Reading text OBJ file", 0, aNbMiBTotal, 1);
|
||||
OSD_Timer aTimer;
|
||||
aTimer.Start();
|
||||
|
||||
// Each node in the Element specifies independent indices of Vertex position, Texture coordinates and Normal.
|
||||
// This scheme does not match natural definition of Primitive Array where each unique set of nodal properties defines Vertex
|
||||
// (thus node at the same location but with different normal should be duplicated).
|
||||
// The following code converts OBJ definition of nodal properties to Primitive Array definition.
|
||||
NCollection_Vector<Graphic3d_Vec3> aVerts;
|
||||
NCollection_Vector<Graphic3d_Vec2> aVertParams;
|
||||
NCollection_Vector<Graphic3d_Vec3> aNorms;
|
||||
NCollection_DataMap<Graphic3d_Vec3i, Standard_Integer, ObjVec3iHasher> aPackedIndices;
|
||||
NCollection_DataMap<TCollection_AsciiString, MeshMaterial> aMaterials;
|
||||
TCollection_AsciiString anActiveMat;
|
||||
MeshGroup aGroup;
|
||||
|
||||
const size_t aMemLimitBytes = theMemLimitMiB == -1
|
||||
? size_t(-1)
|
||||
: (theMemLimitMiB * 1024 * 1024);
|
||||
size_t aMemEstim = 0;
|
||||
|
||||
char aLine[256] = {};
|
||||
Standard_Integer aNbLines = 0;
|
||||
bool isStart = true;
|
||||
for (; ::feof (aFile.File) == 0 && ::fgets (aLine, 255, aFile.File) != NULL; )
|
||||
{
|
||||
++aNbLines;
|
||||
if (aTimer.ElapsedTime() > 1.0)
|
||||
{
|
||||
if (!aPSentry.More())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const Standard_Integer aNbMiBRead = Standard_Integer(::ftell64 (aFile.File) / (1024 * 1024));
|
||||
for (; aNbMiBPassed < aNbMiBRead; ++aNbMiBPassed) { aPSentry.Next(); }
|
||||
aTimer.Reset();
|
||||
aTimer.Start();
|
||||
}
|
||||
|
||||
const char* aPos = aLine;
|
||||
if (*aLine == '#')
|
||||
{
|
||||
if (isStart)
|
||||
{
|
||||
TCollection_AsciiString aComment (aLine + 1);
|
||||
aComment.LeftAdjust();
|
||||
aComment.RightAdjust();
|
||||
if (!aComment.IsEmpty())
|
||||
{
|
||||
myComments.Append (aComment);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (*aLine == '\n'
|
||||
|| *aLine == '\0')
|
||||
{
|
||||
|
||||
continue;
|
||||
}
|
||||
isStart = false;
|
||||
|
||||
if (::memcmp (aLine, "v ", 2) == 0)
|
||||
{
|
||||
aPos += 2;
|
||||
char* aNext = NULL;
|
||||
Graphic3d_Vec3 aVert;
|
||||
objReadVec3 (aPos, aNext, aVert);
|
||||
aPos = aNext;
|
||||
|
||||
aMemEstim += sizeof(Graphic3d_Vec3);
|
||||
if (aMemEstim >= aMemLimitBytes)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
|
||||
+ "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
|
||||
+ "\nMesh data will be truncated!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
aVerts.Append (aVert);
|
||||
}
|
||||
else if (::memcmp (aLine, "vn ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Graphic3d_Vec3 aNorm;
|
||||
objReadVec3 (aPos, aNext, aNorm);
|
||||
aPos = aNext;
|
||||
|
||||
aMemEstim += sizeof(Graphic3d_Vec3);
|
||||
if (aMemEstim >= aMemLimitBytes)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
|
||||
+ "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
|
||||
+ "\nMesh data will be truncated!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
aNorms.Append (aNorm);
|
||||
}
|
||||
else if (::memcmp (aLine, "vt ", 3) == 0)
|
||||
{
|
||||
aPos += 3;
|
||||
char* aNext = NULL;
|
||||
Graphic3d_Vec2 anUV;
|
||||
anUV.x() = (float )Strtod (aPos, &aNext);
|
||||
aPos = aNext;
|
||||
anUV.y() = (float )Strtod (aPos, &aNext);
|
||||
aPos = aNext;
|
||||
|
||||
aMemEstim += sizeof(Graphic3d_Vec2);
|
||||
if (aMemEstim >= aMemLimitBytes)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
|
||||
+ "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
|
||||
+ "\nMesh data will be truncated!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
aVertParams.Append (anUV);
|
||||
}
|
||||
else if (::memcmp (aLine, "f ", 2) == 0)
|
||||
{
|
||||
aPos += 2;
|
||||
char* aNext = NULL;
|
||||
|
||||
Graphic3d_Vec4i aTriNodes (-1, -1, -1, -1);
|
||||
for (int aNode = 0; aNode < 4; ++aNode)
|
||||
{
|
||||
Graphic3d_Vec3i a3Indices (-1, -1, -1);
|
||||
a3Indices[0] = strtol (aPos, &aNext, 10) - 1;
|
||||
if (aNext == aPos)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse UV index
|
||||
aPos = aNext;
|
||||
if (*aPos == '/')
|
||||
{
|
||||
++aPos;
|
||||
a3Indices[1] = strtol (aPos, &aNext, 10) - 1;
|
||||
aPos = aNext;
|
||||
|
||||
// parse Normal index
|
||||
if (*aPos == '/')
|
||||
{
|
||||
++aPos;
|
||||
a3Indices[2] = strtol (aPos, &aNext, 10) - 1;
|
||||
aPos = aNext;
|
||||
}
|
||||
}
|
||||
if (*aPos != ' '
|
||||
&& *aPos != '\n'
|
||||
&& *aPos != '\0')
|
||||
{
|
||||
++aPos;
|
||||
}
|
||||
|
||||
// handle negative indices
|
||||
if (a3Indices[0] < -1)
|
||||
{
|
||||
a3Indices[0] += aVerts.Upper() + 2;
|
||||
}
|
||||
if (a3Indices[1] < -1)
|
||||
{
|
||||
a3Indices[1] += aVertParams.Upper() + 2;
|
||||
}
|
||||
if (a3Indices[2] < -1)
|
||||
{
|
||||
a3Indices[2] += aNorms.Upper() + 2;
|
||||
}
|
||||
|
||||
Standard_Integer anIndex = -1;
|
||||
if (!aPackedIndices.Find (a3Indices, anIndex))
|
||||
{
|
||||
if (a3Indices[0] >= 0)
|
||||
{
|
||||
aMemEstim += sizeof(Graphic3d_Vec3);
|
||||
}
|
||||
if (a3Indices[1] >= 0)
|
||||
{
|
||||
aMemEstim += sizeof(Graphic3d_Vec2);
|
||||
}
|
||||
if (a3Indices[2] >= 0)
|
||||
{
|
||||
aMemEstim += sizeof(Graphic3d_Vec3);
|
||||
}
|
||||
aMemEstim += sizeof(Graphic3d_Vec4i) + sizeof(Standard_Integer); // naive map
|
||||
if (aMemEstim >= aMemLimitBytes)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
|
||||
+ "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
|
||||
+ "\nMesh data will be truncated!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if (a3Indices[0] < aVerts.Lower() || a3Indices[0] > aVerts.Upper())
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
AddNodePosition (aVerts.Value (a3Indices[0]));
|
||||
aGroup.NodeUpper = myNodes.Upper();
|
||||
if (aGroup.NodeLower < 0)
|
||||
{
|
||||
aGroup.NodeLower = aGroup.NodeUpper;
|
||||
}
|
||||
if (a3Indices[1] >= 0)
|
||||
{
|
||||
if (a3Indices[1] < aVertParams.Lower() || a3Indices[1] > aVertParams.Upper())
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
AddNodeUV (aVertParams.Value (a3Indices[1]));
|
||||
}
|
||||
if (a3Indices[2] >= 0)
|
||||
{
|
||||
if (a3Indices[2] < aNorms.Lower() || a3Indices[2] > aNorms.Upper())
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
AddNodeNormal (aNorms.Value (a3Indices[2]));
|
||||
}
|
||||
anIndex = myNodes.Upper();
|
||||
aPackedIndices.Bind (a3Indices, anIndex);
|
||||
}
|
||||
aTriNodes[aNode] = anIndex;
|
||||
}
|
||||
|
||||
if (aTriNodes[0] < 0
|
||||
|| aTriNodes[1] < 0
|
||||
|| aTriNodes[2] < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
aMemEstim += sizeof(Graphic3d_Vec4i);
|
||||
if (aMemEstim >= aMemLimitBytes)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
|
||||
+ "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
|
||||
+ "\nMesh data will be truncated!", Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
AddElement (aTriNodes);
|
||||
aGroup.ElemUpper = myElements.Upper();
|
||||
if (aGroup.ElemLower < 0)
|
||||
{
|
||||
aGroup.ElemLower = aGroup.ElemUpper;
|
||||
if (!anActiveMat.IsEmpty())
|
||||
{
|
||||
aMaterials.Find (anActiveMat, aGroup.Material);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "g ", 2) == 0)
|
||||
{
|
||||
if (aGroup.ElemLower >= 0
|
||||
&& aGroup.ElemLower != aGroup.ElemUpper)
|
||||
{
|
||||
myGroups.Append (aGroup);
|
||||
aGroup = MeshGroup();
|
||||
aPackedIndices.Clear(); // vertices might be duplicated after this...
|
||||
}
|
||||
|
||||
TCollection_AsciiString aGroupName;
|
||||
if (!objReadName (aPos + 2, aGroupName))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Warning);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (::memcmp (aLine, "mtllib ", 7) == 0)
|
||||
{
|
||||
TCollection_AsciiString aMatPath;
|
||||
if (!objReadName (aPos + 7, aMatPath))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
ObjMaterialReader aMatReader (aMaterials);
|
||||
aMatReader.Read (aFolder, aMatPath);
|
||||
}
|
||||
else if (::memcmp (aLine, "usemtl ", 7) == 0)
|
||||
{
|
||||
TCollection_AsciiString aMatName;
|
||||
if (!objReadName (aPos + 7, aMatName))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Warning);
|
||||
continue;
|
||||
}
|
||||
else if (!aMaterials.IsBound (aMatName))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString("Use of undefined OBJ material at line ") + aNbLines, Message_Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
anActiveMat = aMatName;
|
||||
}
|
||||
}
|
||||
|
||||
if (aGroup.ElemLower >= 0
|
||||
&& aGroup.ElemLower != aGroup.ElemUpper)
|
||||
{
|
||||
myGroups.Append (aGroup);
|
||||
}
|
||||
|
||||
for (; aNbMiBPassed < aNbMiBTotal; ++aNbMiBPassed) { aPSentry.Next(); }
|
||||
return Standard_True;
|
||||
}
|
43
src/MeshVS/ObjDataSource.h
Normal file
43
src/MeshVS/ObjDataSource.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef ObjDataSource_H
|
||||
#define ObjDataSource_H
|
||||
|
||||
#include <MeshDataSource.h>
|
||||
|
||||
//! The DataSource for working with OBJ mesh reader.
|
||||
class ObjDataSource : public MeshDataSource
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT ObjDataSource();
|
||||
|
||||
//! Read the mesh from specified file.
|
||||
Standard_EXPORT virtual Standard_Boolean Read (const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& theProgress,
|
||||
const Standard_Integer theIndexLimit,
|
||||
const Standard_Integer theMemoryLimitMiB) Standard_OVERRIDE;
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(ObjDataSource, MeshDataSource)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(ObjDataSource, MeshDataSource)
|
||||
|
||||
#endif // ObjDataSource_H
|
354
src/MeshVS/ObjDataWriter.cpp
Normal file
354
src/MeshVS/ObjDataWriter.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <ObjDataWriter.h>
|
||||
|
||||
#include <FaceIterator.h>
|
||||
#include <CafShapePrs.h>
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepLProp_SLProps.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Message_ProgressSentry.hxx>
|
||||
#include <OSD_OpenFile.hxx>
|
||||
#include <Poly_Array1OfTriangle.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Standard_CLocaleSentry.hxx>
|
||||
#include <TDataStd_Name.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(ObjDataWriter, Standard_Transient)
|
||||
|
||||
//! Auxiliary class to write OBJ.
|
||||
class ObjWriter
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
ObjWriter (const TCollection_AsciiString& theName,
|
||||
const Standard_Boolean theHasNormals)
|
||||
: myFile (OSD_OpenFile (theName.ToCString(), "wb")),
|
||||
myName (theName),
|
||||
myHasNormals (theHasNormals == Standard_True)
|
||||
{
|
||||
if (myFile == NULL)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("File can not be created!\n") + theName, Message_Fail);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//! Destructor, will emit error message if file was not closed.
|
||||
~ObjWriter()
|
||||
{
|
||||
if (myFile != NULL)
|
||||
{
|
||||
::fclose (myFile);
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("File can not be written!\n") + myName, Message_Fail);
|
||||
}
|
||||
}
|
||||
|
||||
//! Return true if file has been opened.
|
||||
bool IsOpened() const { return myFile != NULL; }
|
||||
|
||||
//! Correctly close the file.
|
||||
void Close()
|
||||
{
|
||||
::fclose (myFile);
|
||||
myFile = NULL;
|
||||
}
|
||||
|
||||
//! Write the header.
|
||||
bool WriteHeader (const Standard_Integer theNbNodes,
|
||||
const Standard_Integer theNbElems)
|
||||
{
|
||||
return ::Fprintf (myFile, "# Exported by OpenCASCADE CAD Assistant [www.opencascade.com]\n"
|
||||
"# Vertices: %d\n"
|
||||
"# Faces: %d\n", theNbNodes, theNbElems) != 0;
|
||||
}
|
||||
|
||||
//! Writing a triangle
|
||||
bool WriteTriangle (const Graphic3d_Vec4i& theTri)
|
||||
{
|
||||
if (myHasNormals)
|
||||
{
|
||||
return Fprintf (myFile, "f %d//%d %d//%d %d//%d\n",
|
||||
theTri[0] + 1, theTri[0] + 1,
|
||||
theTri[1] + 1, theTri[1] + 1,
|
||||
theTri[2] + 1, theTri[2] + 1) != 0;
|
||||
}
|
||||
return Fprintf (myFile, "f %d %d %d\n",
|
||||
theTri[0] + 1,
|
||||
theTri[1] + 1,
|
||||
theTri[2] + 1) != 0;
|
||||
}
|
||||
|
||||
//! Writing a quad
|
||||
bool WriteQuad (const Graphic3d_Vec4i& theQuad)
|
||||
{
|
||||
if (myHasNormals)
|
||||
{
|
||||
return Fprintf (myFile, "f %d//%d %d//%d %d//%d %d//%d\n",
|
||||
theQuad[0] + 1, theQuad[0] + 1,
|
||||
theQuad[1] + 1, theQuad[1] + 1,
|
||||
theQuad[2] + 1, theQuad[2] + 1,
|
||||
theQuad[3] + 1, theQuad[3] + 1) != 0;
|
||||
}
|
||||
return Fprintf (myFile, "f %d %d %d %d\n",
|
||||
theQuad[0] + 1,
|
||||
theQuad[1] + 1,
|
||||
theQuad[2] + 1,
|
||||
theQuad[3] + 1) != 0;
|
||||
}
|
||||
|
||||
//! Writing a vector
|
||||
bool WriteVertex (const Graphic3d_Vec3& theValue)
|
||||
{
|
||||
return Fprintf (myFile, "v %f %f %f\n", theValue.x(), theValue.y(), theValue.z()) != 0;
|
||||
}
|
||||
|
||||
//! Writing a vector
|
||||
bool WriteNormal (const Graphic3d_Vec3& theValue)
|
||||
{
|
||||
return Fprintf (myFile, "vn %f %f %f\n", theValue.x(), theValue.y(), theValue.z()) != 0;
|
||||
}
|
||||
|
||||
//! Writing a group name
|
||||
bool WriteGroup (const TCollection_AsciiString& theValue)
|
||||
{
|
||||
return Fprintf (myFile, "g %s\n", theValue.ToCString()) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
FILE* myFile;
|
||||
TCollection_AsciiString myName;
|
||||
bool myHasNormals;
|
||||
bool myIsOpened;
|
||||
|
||||
};
|
||||
|
||||
//================================================================
|
||||
// Function : Constructor
|
||||
// Purpose :
|
||||
//================================================================
|
||||
ObjDataWriter::ObjDataWriter()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : Write
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Standard_Boolean ObjDataWriter::Write (const Handle(MeshDataSource)& theDataSrc,
|
||||
const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& /*theProgress*/)
|
||||
{
|
||||
if (theDataSrc.IsNull())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// header
|
||||
/*NCollection_IndexedMap<TCollection_AsciiString> aComments;
|
||||
for (NCollection_Sequence<TCollection_AsciiString>::Iterator aCommentIter (theDataSrc->FileComments()); aCommentIter.More(); aCommentIter.Next())
|
||||
{
|
||||
aComments.Add (aCommentIter.Value());
|
||||
}
|
||||
aComments.Add ("Exported by OpenCASCADE CAD Assistant [www.opencascade.com]");*/
|
||||
|
||||
Standard_CLocaleSentry aLocaleSentry;
|
||||
ObjWriter anObjFile (theFile, theDataSrc->HasNormals());
|
||||
if (!anObjFile.IsOpened()
|
||||
|| !anObjFile.WriteHeader (theDataSrc->NbNodes(), theDataSrc->NbElements()))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
for (Standard_Integer aNodeIter = 0; aNodeIter < theDataSrc->NbNodes(); ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNode = theDataSrc->Nodes().Value (aNodeIter);
|
||||
if (!anObjFile.WriteVertex (aNode))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
if (theDataSrc->HasNormals())
|
||||
{
|
||||
for (Standard_Integer aNodeIter = 0; aNodeIter < theDataSrc->NbNodes(); ++aNodeIter)
|
||||
{
|
||||
const Graphic3d_Vec3& aNormal = theDataSrc->Normals().Value (aNodeIter);
|
||||
if (!anObjFile.WriteNormal (aNormal))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Standard_Integer anElemIter = 0; anElemIter < theDataSrc->NbElements(); ++anElemIter)
|
||||
{
|
||||
const Graphic3d_Vec4i& anElem = theDataSrc->Elements().Value (anElemIter);
|
||||
if (anElem[3] == -1)
|
||||
{
|
||||
if (!anObjFile.WriteTriangle (anElem))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!anObjFile.WriteQuad (anElem))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
anObjFile.Close();
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//! Trivial convertor
|
||||
inline Graphic3d_Vec3 objXyzToVec (const gp_XYZ& thePnt)
|
||||
{
|
||||
return Graphic3d_Vec3 ((float )thePnt.X(), (float )thePnt.Y(), (float )thePnt.Z());
|
||||
}
|
||||
|
||||
//================================================================
|
||||
// Function : Write
|
||||
// Purpose :
|
||||
//================================================================
|
||||
Standard_Boolean ObjDataWriter::Write (const AIS_ListOfInteractive& thePrsList,
|
||||
const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& /*theProgress*/)
|
||||
{
|
||||
if (thePrsList.IsEmpty())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
Standard_Integer aNbNodesAll = 0;
|
||||
Standard_Integer aNbElemsAll = 0;
|
||||
for (FaceIterator aFaceIter (thePrsList); aFaceIter.More(); aFaceIter.Next())
|
||||
{
|
||||
aNbNodesAll += aFaceIter.Triangulation->Nodes().Length();
|
||||
aNbElemsAll += aFaceIter.Triangulation->Triangles().Length();
|
||||
}
|
||||
|
||||
if (aNbNodesAll == 0
|
||||
|| aNbElemsAll == 0)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("No mesh data to save!\n"), Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
Standard_CLocaleSentry aLocaleSentry;
|
||||
ObjWriter anObjFile (theFile, Standard_True);
|
||||
if (!anObjFile.IsOpened()
|
||||
|| !anObjFile.WriteHeader (aNbNodesAll, aNbElemsAll))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// write vertices
|
||||
BRepAdaptor_Surface aFaceAdaptor;
|
||||
BRepLProp_SLProps aSLTool (1, 1e-12);
|
||||
gp_Dir aNormal;
|
||||
Standard_Integer aFirstNode = 0;
|
||||
Graphic3d_Vec4i aTriNodes (-1, -1, -1, -1);
|
||||
Standard_Integer aNbFaces = 0;
|
||||
TCollection_AsciiString aPrevGroup;
|
||||
for (FaceIterator aFaceIter (thePrsList); aFaceIter.More(); aFaceIter.Next())
|
||||
{
|
||||
++aNbFaces;
|
||||
const Standard_Integer aLower = aFaceIter.Triangulation->Triangles().Lower();
|
||||
const Standard_Boolean isMirrored = aFaceIter.Trsf.VectorialPart().Determinant() < 0.0;
|
||||
const Handle(Poly_Triangulation)& aTriangulation = aFaceIter.Triangulation;
|
||||
|
||||
TCollection_AsciiString aRefName;
|
||||
Handle(TDataStd_Name) aNodeName;
|
||||
if (aFaceIter.ShapePrs->GetLabel().FindAttribute (TDataStd_Name::GetID(), aNodeName))
|
||||
{
|
||||
aRefName = TCollection_AsciiString (aNodeName->Get());
|
||||
}
|
||||
if (!aRefName.IsEmpty()
|
||||
&& !aRefName.IsEqual (aPrevGroup)
|
||||
&& !anObjFile.WriteGroup (aRefName))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// write nodes
|
||||
const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
|
||||
const gp_Trsf aTrsf = aFaceIter.Trsf;
|
||||
for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
gp_Pnt aNode = aNodes (aNodeIter);
|
||||
aNode.Transform (aTrsf);
|
||||
if (!anObjFile.WriteVertex (objXyzToVec (aNode.XYZ())))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
// write normals
|
||||
TopoDS_Face aFace = TopoDS::Face (aFaceIter.Face.Oriented (TopAbs_FORWARD));
|
||||
aFace.Location (TopLoc_Location());
|
||||
aFaceAdaptor.Initialize (aFace, Standard_False);
|
||||
aSLTool.SetSurface (aFaceAdaptor);
|
||||
const TColgp_Array1OfPnt2d& aNodeUVs = aTriangulation->UVNodes();
|
||||
for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
const gp_XY& anUV = aNodeUVs.Value (aNodeIter).XY();
|
||||
aSLTool.SetParameters (anUV.X(), anUV.Y());
|
||||
gp_Dir aNormal ((aSLTool.IsNormalDefined() ? aSLTool.Normal() : gp::DZ()).XYZ());
|
||||
aNormal.Transform (aTrsf);
|
||||
if (aFaceIter.Face.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
aNormal.Reverse();
|
||||
}
|
||||
if (!anObjFile.WriteNormal (objXyzToVec (aNormal.XYZ())))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
// write indices
|
||||
for (Poly_Array1OfTriangle::Iterator anElemIter (aFaceIter.Triangulation->Triangles()); anElemIter.More(); anElemIter.Next())
|
||||
{
|
||||
if ((aFaceIter.Face.Orientation() == TopAbs_REVERSED) ^ isMirrored)
|
||||
{
|
||||
anElemIter.Value().Get (aTriNodes[0], aTriNodes[2], aTriNodes[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
anElemIter.Value().Get (aTriNodes[0], aTriNodes[1], aTriNodes[2]);
|
||||
}
|
||||
aTriNodes[0] = aFirstNode + aTriNodes[0] - aLower;
|
||||
aTriNodes[1] = aFirstNode + aTriNodes[1] - aLower;
|
||||
aTriNodes[2] = aFirstNode + aTriNodes[2] - aLower;
|
||||
if (!anObjFile.WriteTriangle (aTriNodes))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
aFirstNode += aFaceIter.Triangulation->NbNodes();
|
||||
}
|
||||
|
||||
anObjFile.Close();
|
||||
return Standard_True;
|
||||
}
|
49
src/MeshVS/ObjDataWriter.h
Normal file
49
src/MeshVS/ObjDataWriter.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef ObjDataWriter_H
|
||||
#define ObjDataWriter_H
|
||||
|
||||
#include <MeshDataSource.h>
|
||||
|
||||
#include <AIS_ListOfInteractive.hxx>
|
||||
|
||||
//! Mesh writer to the OBJ format.
|
||||
class ObjDataWriter : public Standard_Transient
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT ObjDataWriter();
|
||||
|
||||
//! Write the mesh into specified file.
|
||||
Standard_EXPORT Standard_Boolean Write (const Handle(MeshDataSource)& theDataSrc,
|
||||
const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& theProgress);
|
||||
|
||||
//! Write the mesh presentation of the model into specified file.
|
||||
Standard_EXPORT Standard_Boolean Write (const AIS_ListOfInteractive& thePrsList,
|
||||
const TCollection_AsciiString& theFile,
|
||||
const Handle(Message_ProgressIndicator)& theProgress);
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(ObjDataWriter, Standard_Transient)
|
||||
|
||||
};
|
||||
|
||||
DEFINE_STANDARD_HANDLE(ObjDataWriter, Standard_Transient)
|
||||
|
||||
#endif // ObjDataWriter_H
|
@@ -101,6 +101,7 @@ OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnectio
|
||||
Graphic3d_ZLayerSettings anUnderlaySettings;
|
||||
anUnderlaySettings.Flags = 0;
|
||||
anUnderlaySettings.IsImmediate = false;
|
||||
anUnderlaySettings.UseEnvironmentTexture = false;
|
||||
myLayerIds.Add (Graphic3d_ZLayerId_BotOSD);
|
||||
myLayerSeq.Append (Graphic3d_ZLayerId_BotOSD);
|
||||
myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_BotOSD, anUnderlaySettings);
|
||||
@@ -133,6 +134,7 @@ OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Handle(Aspect_DisplayConnectio
|
||||
Graphic3d_ZLayerSettings anOsdSettings;
|
||||
anOsdSettings.Flags = 0;
|
||||
anOsdSettings.IsImmediate = true;
|
||||
anOsdSettings.UseEnvironmentTexture = false;
|
||||
myLayerIds.Add (Graphic3d_ZLayerId_TopOSD);
|
||||
myLayerSeq.Append (Graphic3d_ZLayerId_TopOSD);
|
||||
myMapOfZLayerSettings.Bind (Graphic3d_ZLayerId_TopOSD, anOsdSettings);
|
||||
|
@@ -365,6 +365,14 @@ void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
|
||||
glDepthFunc (GL_ALWAYS);
|
||||
}
|
||||
|
||||
// save environment texture
|
||||
Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
|
||||
if (!myLayerSettings.UseEnvironmentTexture)
|
||||
{
|
||||
Handle(OpenGl_Texture) anEmptyTexture;
|
||||
theWorkspace->SetEnvironmentTexture (anEmptyTexture);
|
||||
}
|
||||
|
||||
// handle depth offset
|
||||
if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
|
||||
{
|
||||
@@ -390,4 +398,10 @@ void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
|
||||
theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
|
||||
anAppliedOffsetParams.factor,
|
||||
anAppliedOffsetParams.units);
|
||||
|
||||
// restore environment texture
|
||||
if (!myLayerSettings.UseEnvironmentTexture)
|
||||
{
|
||||
theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,6 @@
|
||||
#define OPENGL_NS_ANTIALIASING (1<<5)
|
||||
#define OPENGL_NS_2NDPASSNEED (1<<6)
|
||||
#define OPENGL_NS_2NDPASSDO (1<<7)
|
||||
#define OPENGL_NS_FORBIDSETTEX (1<<8)
|
||||
#define OPENGL_NS_WHITEBACK (1<<9)
|
||||
#define OPENGL_NS_WHITEBACK (1<<8)
|
||||
|
||||
#endif //_OpenGl_NamedStatus_Header
|
||||
|
@@ -520,6 +520,18 @@ Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(Ope
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OpenGl_RaytraceClipPlanes
|
||||
// purpose : Creates new set of clipping planes
|
||||
// =======================================================================
|
||||
OpenGl_RaytraceClipPlanes::OpenGl_RaytraceClipPlanes()
|
||||
{
|
||||
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < MAX_PLANE_NUMBER; ++aPlaneIdx)
|
||||
{
|
||||
myClipPlanes[aPlaneIdx * 2] = BVH_Vec4f (-1.f, -1.f, -1.f, -1.f);
|
||||
}
|
||||
}
|
||||
|
||||
namespace OpenGl_Raytrace
|
||||
{
|
||||
// =======================================================================
|
||||
|
@@ -223,6 +223,133 @@ private:
|
||||
|
||||
};
|
||||
|
||||
//! Set of clipping planes specific for OpenGL primitive array.
|
||||
class OpenGl_RaytraceClipPlanes
|
||||
{
|
||||
public:
|
||||
|
||||
//! Maximum number of clipping planes used in ray-tracing for each
|
||||
//! OpenGL primitive array. This is not implementation restriction,
|
||||
//! but it is reasonable to limit max number of planes in order to
|
||||
//! simplify GLSL data representation.
|
||||
static const Standard_Integer MAX_PLANE_NUMBER = 8;
|
||||
|
||||
//! State of clipping plane.
|
||||
enum ClipPlaneState {
|
||||
|
||||
CLIP_PLANE_OFF = -1, //!< plane is deactivated
|
||||
CLIP_PLANE_VIEW = 0, //!< plane is in view space
|
||||
CLIP_PLANE_WORLD = 1 //!< plane is in world space
|
||||
};
|
||||
|
||||
//! Wrapper for clipping plane configuration.
|
||||
class ClipPlane
|
||||
{
|
||||
public:
|
||||
|
||||
//! Creates new clipping plane wrapper.
|
||||
ClipPlane (BVH_Vec4f& theSettings,
|
||||
BVH_Vec4f& theEquation) : mySettings (theSettings),
|
||||
myEquation (theEquation) {}
|
||||
|
||||
//! Sets 4D equation vector for clipping plane.
|
||||
void SetEquation (const BVH_Vec4d& theEquation, const ClipPlaneState theState = CLIP_PLANE_WORLD)
|
||||
{
|
||||
for (Standard_Integer anIndex = 0; anIndex < 4; ++anIndex)
|
||||
{
|
||||
myEquation[anIndex] = static_cast<Standard_ShortReal> (theEquation[anIndex]);
|
||||
}
|
||||
|
||||
SetState (theState);
|
||||
}
|
||||
|
||||
//! Returns state of clipping plane.
|
||||
ClipPlaneState State()
|
||||
{
|
||||
return static_cast<ClipPlaneState> ((int)mySettings.x());
|
||||
}
|
||||
|
||||
//! Sets state of clipping plane.
|
||||
void SetState (const ClipPlaneState theState)
|
||||
{
|
||||
mySettings.x() = static_cast<Standard_ShortReal> (theState);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//! Settings of clipping plane.
|
||||
BVH_Vec4f& mySettings;
|
||||
|
||||
//! 4D equation vector of clipping plane.
|
||||
BVH_Vec4f& myEquation;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//! Creates new set of clipping planes.
|
||||
OpenGl_RaytraceClipPlanes();
|
||||
|
||||
//! Returns clipping plane for the given index.
|
||||
ClipPlane operator[] (const Standard_Integer theIndex)
|
||||
{
|
||||
return ClipPlane (myClipPlanes[theIndex * 2 + 0],
|
||||
myClipPlanes[theIndex * 2 + 1]);
|
||||
}
|
||||
|
||||
//! Returns packed (serialized) representation of clipping planes set.
|
||||
const Standard_ShortReal* Packed()
|
||||
{
|
||||
return reinterpret_cast<Standard_ShortReal*> (this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//! Serialized clipping planes storage.
|
||||
BVH_Vec4f myClipPlanes[MAX_PLANE_NUMBER * 2];
|
||||
|
||||
};
|
||||
|
||||
//! Stores transform properties of ray-tracing object.
|
||||
class OpenGl_RaytraceTransform : public BVH_Transform<Standard_ShortReal, 4>
|
||||
{
|
||||
public:
|
||||
|
||||
//! Value of invalid clipping plane set.
|
||||
static const Standard_Integer NO_CLIPPING = -1;
|
||||
|
||||
public:
|
||||
|
||||
//! Creates new identity transformation.
|
||||
OpenGl_RaytraceTransform() : BVH_Transform<Standard_ShortReal, 4>()
|
||||
{
|
||||
myClipSetID = NO_CLIPPING; // no clipping by default
|
||||
}
|
||||
|
||||
//! Creates new transformation with specified matrix.
|
||||
OpenGl_RaytraceTransform (const BVH_Mat4f& theTransform) : BVH_Transform<Standard_ShortReal, 4> (theTransform)
|
||||
{
|
||||
myClipSetID = NO_CLIPPING; // no clipping by default
|
||||
}
|
||||
|
||||
//! Returns ID of associated set of clipping planes.
|
||||
Standard_Integer ClipSetID() const
|
||||
{
|
||||
return myClipSetID;
|
||||
}
|
||||
|
||||
//! Sets ID of associated set of clipping planes.
|
||||
void SetClipSetID (const Standard_Integer theClipSetID)
|
||||
{
|
||||
myClipSetID = theClipSetID;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! ID of associated set of clipping planes.
|
||||
Standard_Integer myClipSetID;
|
||||
|
||||
};
|
||||
|
||||
//! Stores geometry of ray-tracing scene.
|
||||
class OpenGl_RaytraceGeometry : public BVH_Geometry<Standard_ShortReal, 3>
|
||||
{
|
||||
@@ -235,7 +362,7 @@ public:
|
||||
//! This is not restriction of the solution implemented, but
|
||||
//! rather the reasonable limit of the number of textures in
|
||||
//! various applications (can be increased if needed).
|
||||
static const Standard_Integer MAX_TEX_NUMBER = 32;
|
||||
static const Standard_Integer MAX_TEX_NUMBER = 128;
|
||||
|
||||
public:
|
||||
|
||||
@@ -247,6 +374,10 @@ public:
|
||||
std::vector<OpenGl_RaytraceMaterial,
|
||||
NCollection_StdAllocator<OpenGl_RaytraceMaterial> > Materials;
|
||||
|
||||
//! Array of sets of clipping plane parameters.
|
||||
std::vector<OpenGl_RaytraceClipPlanes,
|
||||
NCollection_StdAllocator<OpenGl_RaytraceClipPlanes> > ClipPlanes;
|
||||
|
||||
//! Global ambient from all light sources.
|
||||
BVH_Vec4f Ambient;
|
||||
|
||||
|
@@ -824,25 +824,6 @@ const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(Op
|
||||
return &myMaterialStates.Find (theProgram);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SurfaceDetailState
|
||||
// purpose : Returns current state of OCCT surface detail
|
||||
// =======================================================================
|
||||
const OpenGl_SurfaceDetailState& OpenGl_ShaderManager::SurfaceDetailState() const
|
||||
{
|
||||
return mySurfaceDetailState;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : UpdateSurfaceDetailStateTo
|
||||
// purpose : Updates state of OCCT surface detail
|
||||
// =======================================================================
|
||||
void OpenGl_ShaderManager::UpdateSurfaceDetailStateTo (const Graphic3d_TypeOfSurfaceDetail theDetail)
|
||||
{
|
||||
mySurfaceDetailState.Set (theDetail);
|
||||
mySurfaceDetailState.Update();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include <Graphic3d_ShaderProgram.hxx>
|
||||
#include <Graphic3d_StereoMode.hxx>
|
||||
#include <Graphic3d_TypeOfShadingModel.hxx>
|
||||
#include <Graphic3d_TypeOfSurfaceDetail.hxx>
|
||||
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
@@ -253,14 +252,6 @@ public:
|
||||
//! Returns current state of OCCT material for specified program.
|
||||
Standard_EXPORT const OpenGl_MaterialState* MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
|
||||
|
||||
public:
|
||||
|
||||
//! Returns current state of OCCT surface detail.
|
||||
Standard_EXPORT const OpenGl_SurfaceDetailState& SurfaceDetailState() const;
|
||||
|
||||
//! Updates state of OCCT surface detail.
|
||||
Standard_EXPORT void UpdateSurfaceDetailStateTo (const Graphic3d_TypeOfSurfaceDetail theDetail);
|
||||
|
||||
public:
|
||||
|
||||
//! Pushes current state of OCCT graphics parameters to specified program.
|
||||
@@ -309,7 +300,7 @@ protected:
|
||||
{
|
||||
aBits |= OpenGl_PO_ClipPlanes;
|
||||
}
|
||||
if (theEnableEnvMap && mySurfaceDetailState.Detail() == Graphic3d_TOD_ENVIRONMENT)
|
||||
if (theEnableEnvMap)
|
||||
{
|
||||
// Environment map overwrites material texture
|
||||
aBits |= OpenGl_PO_TextureEnv;
|
||||
@@ -413,7 +404,6 @@ protected:
|
||||
OpenGl_WorldViewState myWorldViewState; //!< State of OCCT world-view transformation
|
||||
OpenGl_ClippingState myClippingState; //!< State of OCCT clipping planes
|
||||
OpenGl_LightSourceState myLightSourceState; //!< State of OCCT light sources
|
||||
OpenGl_SurfaceDetailState mySurfaceDetailState; //!< State of OCCT surface detail
|
||||
|
||||
private:
|
||||
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#ifndef _OpenGl_State_HeaderFile
|
||||
#define _OpenGl_State_HeaderFile
|
||||
|
||||
#include <Graphic3d_TypeOfSurfaceDetail.hxx>
|
||||
#include <InterfaceGraphic_tgl_all.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <OpenGl_Element.hxx>
|
||||
@@ -183,28 +182,4 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
//! Defines generic state of OCCT surface detail.
|
||||
class OpenGl_SurfaceDetailState : public OpenGl_StateInterface
|
||||
{
|
||||
public:
|
||||
|
||||
//! Creates new surface detail state.
|
||||
OpenGl_SurfaceDetailState (const Graphic3d_TypeOfSurfaceDetail theDetail = Graphic3d_TOD_NONE)
|
||||
: myDetail (theDetail)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//! Sets new surface detail.
|
||||
void Set (const Graphic3d_TypeOfSurfaceDetail theDetail) { myDetail = theDetail; }
|
||||
|
||||
//! Returns surface detail.
|
||||
Graphic3d_TypeOfSurfaceDetail Detail() const { return myDetail; }
|
||||
|
||||
private:
|
||||
|
||||
Graphic3d_TypeOfSurfaceDetail myDetail; //!< OCCT surface detail
|
||||
|
||||
};
|
||||
|
||||
#endif // _OpenGl_State_HeaderFile
|
||||
|
@@ -241,6 +241,20 @@ void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect)
|
||||
myAspectText->SetAspect (theAspect);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetClipPlanes
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_Structure::SetClipPlanes (const Graphic3d_SequenceOfHClipPlane &thePlanes)
|
||||
{
|
||||
Graphic3d_CStructure::SetClipPlanes (thePlanes);
|
||||
|
||||
if (IsRaytracable())
|
||||
{
|
||||
++myModificationState;
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : clearHighlightBox
|
||||
// purpose :
|
||||
|
@@ -129,6 +129,9 @@ public:
|
||||
|
||||
Standard_EXPORT void Clear (const Handle(OpenGl_Context)& theGlCtx);
|
||||
|
||||
//! Pass clip planes to the associated graphic driver structure
|
||||
void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes);
|
||||
|
||||
//! Renders groups of structure without applying any attributes (i.e. transform, material etc).
|
||||
//! @param theWorkspace current workspace
|
||||
//! @param theHasClosed flag will be set to TRUE if structure contains at least one group of closed primitives
|
||||
|
@@ -66,7 +66,6 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
|
||||
myAntiAliasing (Standard_False),
|
||||
myCulling (Standard_True),
|
||||
myShadingModel (Graphic3d_TOSM_FACET),
|
||||
mySurfaceDetail (Graphic3d_TOD_ALL),
|
||||
myBackfacing (Graphic3d_TOBM_AUTOMATIC),
|
||||
myBgColor (myDefaultBg),
|
||||
myFog (myDefaultFog),
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include <Graphic3d_GraduatedTrihedron.hxx>
|
||||
#include <Graphic3d_SequenceOfHClipPlane.hxx>
|
||||
#include <Graphic3d_TypeOfShadingModel.hxx>
|
||||
#include <Graphic3d_TypeOfSurfaceDetail.hxx>
|
||||
#include <Graphic3d_WorldViewProjState.hxx>
|
||||
#include <Graphic3d_ZLayerSettings.hxx>
|
||||
|
||||
@@ -308,16 +307,6 @@ public:
|
||||
//! Sets shading model of the view.
|
||||
virtual void SetShadingModel (const Graphic3d_TypeOfShadingModel theModel) Standard_OVERRIDE { myShadingModel = theModel; }
|
||||
|
||||
//! Returns surface detail type of the view.
|
||||
virtual Graphic3d_TypeOfSurfaceDetail SurfaceDetailType() const Standard_OVERRIDE { return mySurfaceDetail; }
|
||||
|
||||
//! Sets surface detail type of the view.
|
||||
virtual void SetSurfaceDetailType (const Graphic3d_TypeOfSurfaceDetail theType) Standard_OVERRIDE
|
||||
{
|
||||
mySurfaceDetail = theType;
|
||||
myToUpdateEnvironmentMap = Standard_True;
|
||||
}
|
||||
|
||||
//! Return backfacing model used for the view.
|
||||
virtual Graphic3d_TypeOfBackfacingModel BackfacingModel() const Standard_OVERRIDE { return myBackfacing; }
|
||||
|
||||
@@ -562,7 +551,6 @@ protected:
|
||||
Standard_Boolean myAntiAliasing;
|
||||
Standard_Boolean myCulling;
|
||||
Graphic3d_TypeOfShadingModel myShadingModel;
|
||||
Graphic3d_TypeOfSurfaceDetail mySurfaceDetail;
|
||||
Graphic3d_TypeOfBackfacingModel myBackfacing;
|
||||
TEL_COLOUR myBgColor;
|
||||
OPENGL_FOG myFog;
|
||||
@@ -673,10 +661,12 @@ protected: //! @name data types related to ray-tracing
|
||||
OpenGl_RT_uSphereMapForBack,
|
||||
OpenGl_RT_uTexSamplersArray,
|
||||
OpenGl_RT_uBlockedRngEnabled,
|
||||
OpenGl_RT_uMaxRadiance,
|
||||
|
||||
// sampled frame params
|
||||
OpenGl_RT_uSampleWeight,
|
||||
OpenGl_RT_uFrameRndSeed,
|
||||
OpenGl_RT_uBilateralEnabled,
|
||||
|
||||
// adaptive FSAA params
|
||||
OpenGl_RT_uOffsetX,
|
||||
@@ -703,13 +693,14 @@ protected: //! @name data types related to ray-tracing
|
||||
|
||||
OpenGl_RT_RaytraceMaterialTexture = 9,
|
||||
OpenGl_RT_RaytraceLightSrcTexture = 10,
|
||||
OpenGl_RT_RaytraceClippingTexture = 11,
|
||||
|
||||
OpenGl_RT_FsaaInputTexture = 11,
|
||||
OpenGl_RT_PrevAccumTexture = 12,
|
||||
OpenGl_RT_DepthTexture = 13,
|
||||
OpenGl_RT_FsaaInputTexture = 12,
|
||||
OpenGl_RT_PrevAccumTexture = 13,
|
||||
OpenGl_RT_DepthTexture = 14,
|
||||
|
||||
OpenGl_RT_OpenGlColorTexture = 14,
|
||||
OpenGl_RT_OpenGlDepthTexture = 15
|
||||
OpenGl_RT_OpenGlColorTexture = 15,
|
||||
OpenGl_RT_OpenGlDepthTexture = 16
|
||||
};
|
||||
|
||||
//! Tool class for management of shader sources.
|
||||
@@ -1037,6 +1028,8 @@ protected: //! @name fields related to ray-tracing
|
||||
Handle(OpenGl_TextureBufferArb) myRaytraceMaterialTexture;
|
||||
//! Texture buffer of light source properties.
|
||||
Handle(OpenGl_TextureBufferArb) myRaytraceLightSrcTexture;
|
||||
//! Texture buffer of clipping planes parameters.
|
||||
Handle(OpenGl_TextureBufferArb) myRaytraceClippingTexture;
|
||||
|
||||
//! 1st framebuffer (FBO) to perform adaptive FSAA.
|
||||
Handle(OpenGl_FrameBuffer) myRaytraceFBO1[2];
|
||||
|
@@ -403,7 +403,7 @@ Standard_Boolean OpenGl_View::addRaytraceStructure (const OpenGl_Structure*
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// Get structure material
|
||||
// Get material of the structure
|
||||
OpenGl_RaytraceMaterial aStructMaterial;
|
||||
|
||||
if (theStructure->AspectFace() != NULL)
|
||||
@@ -435,6 +435,45 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
|
||||
const Graphic3d_Mat4* theTransform,
|
||||
const Handle(OpenGl_Context)& theGlContext)
|
||||
{
|
||||
// ID of clipping plane set
|
||||
Standard_Integer aClipSetID = -1;
|
||||
|
||||
// Collect clipping planes of structure scope
|
||||
if (!theStructure->ClipPlanes().IsEmpty())
|
||||
{
|
||||
NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
|
||||
|
||||
for (Graphic3d_SequenceOfHClipPlane::Iterator aClipIter (theStructure->ClipPlanes()); aClipIter.More(); aClipIter.Next())
|
||||
{
|
||||
const Handle(Graphic3d_ClipPlane)& aClipPlane = aClipIter.Value();
|
||||
|
||||
if (aClipPlane->IsOn())
|
||||
{
|
||||
if (aUserPlanes.IsNull())
|
||||
{
|
||||
aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
|
||||
}
|
||||
|
||||
aUserPlanes->Append (aClipPlane);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aUserPlanes.IsNull())
|
||||
{
|
||||
myRaytraceGeometry.ClipPlanes.push_back (OpenGl_RaytraceClipPlanes());
|
||||
|
||||
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < aUserPlanes->Size(); ++aPlaneIdx)
|
||||
{
|
||||
if (aPlaneIdx < OpenGl_RaytraceClipPlanes::MAX_PLANE_NUMBER)
|
||||
{
|
||||
myRaytraceGeometry.ClipPlanes.back()[aPlaneIdx].SetEquation (aUserPlanes->operator ()(aPlaneIdx + 1)->GetEquation());
|
||||
}
|
||||
}
|
||||
|
||||
aClipSetID = static_cast<Standard_Integer> (myRaytraceGeometry.ClipPlanes.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next())
|
||||
{
|
||||
// Get group material
|
||||
@@ -476,13 +515,18 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
|
||||
{
|
||||
OpenGl_TriangleSet* aSet = aSetIter->second;
|
||||
|
||||
BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>();
|
||||
OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform;
|
||||
|
||||
if (theTransform != NULL)
|
||||
{
|
||||
aTransform->SetTransform (*theTransform);
|
||||
}
|
||||
|
||||
if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING)
|
||||
{
|
||||
aTransform->SetClipSetID (aClipSetID);
|
||||
}
|
||||
|
||||
aSet->SetProperties (aTransform);
|
||||
|
||||
if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID)
|
||||
@@ -492,18 +536,22 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
|
||||
}
|
||||
else
|
||||
{
|
||||
NCollection_Handle<BVH_Object<Standard_ShortReal, 3> > aSet =
|
||||
addRaytracePrimitiveArray (aPrimArray, aMatID, 0);
|
||||
NCollection_Handle<BVH_Object<Standard_ShortReal, 3> > aSet = addRaytracePrimitiveArray (aPrimArray, aMatID, 0);
|
||||
|
||||
if (!aSet.IsNull())
|
||||
{
|
||||
BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>;
|
||||
OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform;
|
||||
|
||||
if (theTransform != NULL)
|
||||
{
|
||||
aTransform->SetTransform (*theTransform);
|
||||
}
|
||||
|
||||
if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING)
|
||||
{
|
||||
aTransform->SetClipSetID (aClipSetID);
|
||||
}
|
||||
|
||||
aSet->SetProperties (aTransform);
|
||||
|
||||
myRaytraceGeometry.Objects().Append (aSet);
|
||||
@@ -1478,6 +1526,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
|
||||
"uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
|
||||
aShaderProgram->SetSampler (theGlContext,
|
||||
"uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
|
||||
aShaderProgram->SetSampler (theGlContext,
|
||||
"uRaytraceClippingTexture", OpenGl_RT_RaytraceClippingTexture);
|
||||
|
||||
aShaderProgram->SetSampler (theGlContext,
|
||||
"uOpenGlColorTexture", OpenGl_RT_OpenGlColorTexture);
|
||||
@@ -1548,6 +1598,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
|
||||
aShaderProgram->GetUniformLocation (theGlContext, "uSphereMapForBack");
|
||||
myUniformLocations[anIndex][OpenGl_RT_uBlockedRngEnabled] =
|
||||
aShaderProgram->GetUniformLocation (theGlContext, "uBlockedRngEnabled");
|
||||
myUniformLocations[anIndex][OpenGl_RT_uMaxRadiance] =
|
||||
aShaderProgram->GetUniformLocation (theGlContext, "uMaxRadiance");
|
||||
|
||||
myUniformLocations[anIndex][OpenGl_RT_uSampleWeight] =
|
||||
aShaderProgram->GetUniformLocation (theGlContext, "uSampleWeight");
|
||||
@@ -1562,6 +1614,9 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
|
||||
|
||||
theGlContext->BindProgram (myOutImageProgram);
|
||||
|
||||
myUniformLocations[0][OpenGl_RT_uBilateralEnabled] =
|
||||
myOutImageProgram->GetUniformLocation (theGlContext, "uBilateralEnabled");
|
||||
|
||||
myOutImageProgram->SetSampler (theGlContext,
|
||||
"uInputTexture", OpenGl_RT_PrevAccumTexture);
|
||||
|
||||
@@ -1635,6 +1690,7 @@ void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlC
|
||||
|
||||
nullifyResource (theGlContext, myRaytraceLightSrcTexture);
|
||||
nullifyResource (theGlContext, myRaytraceMaterialTexture);
|
||||
nullifyResource (theGlContext, myRaytraceClippingTexture);
|
||||
|
||||
myRaytraceGeometry.ReleaseResources (theGlContext);
|
||||
|
||||
@@ -1770,7 +1826,7 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Create OpenGL BVH buffers
|
||||
// Create BVH buffers
|
||||
|
||||
if (mySceneNodeInfoTexture.IsNull()) // create scene BVH buffers
|
||||
{
|
||||
@@ -1810,6 +1866,9 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Create material buffer
|
||||
|
||||
if (myRaytraceMaterialTexture.IsNull()) // create material buffer
|
||||
{
|
||||
myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
|
||||
@@ -1817,7 +1876,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
|
||||
if (!myRaytraceMaterialTexture->Create (theGlContext))
|
||||
{
|
||||
#ifdef RAY_TRACE_PRINT_INFO
|
||||
std::cout << "Error: Failed to create buffers for material data" << std::endl;
|
||||
std::cout << "Error: Failed to create buffer for material data" << std::endl;
|
||||
#endif
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Create clip planes buffer
|
||||
|
||||
if (myRaytraceClippingTexture.IsNull()) // create clipping planes buffer
|
||||
{
|
||||
myRaytraceClippingTexture = new OpenGl_TextureBufferArb;
|
||||
|
||||
if (!myRaytraceClippingTexture->Create (theGlContext))
|
||||
{
|
||||
#ifdef RAY_TRACE_PRINT_INFO
|
||||
std::cout << "Error: Failed to create buffer for clip plane data" << std::endl;
|
||||
#endif
|
||||
return Standard_False;
|
||||
}
|
||||
@@ -1835,13 +1910,17 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
|
||||
OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
|
||||
myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
|
||||
|
||||
const BVH_Transform<Standard_ShortReal, 4>* aTransform =
|
||||
dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (aTriangleSet->Properties().operator->());
|
||||
const OpenGl_RaytraceTransform* aTransform =
|
||||
dynamic_cast<const OpenGl_RaytraceTransform*> (aTriangleSet->Properties().operator->());
|
||||
|
||||
Standard_ASSERT_RETURN (aTransform != NULL,
|
||||
"OpenGl_TriangleSet does not contain transform", Standard_False);
|
||||
|
||||
aNodeTransforms[anElemIndex] = aTransform->Inversed();
|
||||
|
||||
// Note: write clip plane ID in last matrix component, because
|
||||
// the last matrix row is not used for transformation purposes
|
||||
aNodeTransforms[anElemIndex].SetValue (3, 3, aTransform->ClipSetID());
|
||||
}
|
||||
|
||||
aResult &= mySceneTransformTexture->Init (theGlContext, 4,
|
||||
@@ -2016,6 +2095,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Write clip planes buffer
|
||||
|
||||
if (myRaytraceGeometry.ClipPlanes.size() != 0)
|
||||
{
|
||||
aResult &= myRaytraceClippingTexture->Init (theGlContext, 4,
|
||||
GLsizei (myRaytraceGeometry.ClipPlanes.size() * 16), myRaytraceGeometry.ClipPlanes.front().Packed());
|
||||
|
||||
if (!aResult)
|
||||
{
|
||||
#ifdef RAY_TRACE_PRINT_INFO
|
||||
std::cout << "Error: Failed to upload clipping planes buffer" << std::endl;
|
||||
#endif
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
|
||||
|
||||
#ifdef RAY_TRACE_PRINT_INFO
|
||||
@@ -2166,7 +2262,7 @@ Standard_Boolean OpenGl_View::updateRaytraceEnvironmentMap (const Handle(OpenGl_
|
||||
{
|
||||
aResult &= theGlContext->BindProgram (aProgram);
|
||||
|
||||
if (!myTextureEnv.IsNull() && mySurfaceDetail != Graphic3d_TOD_NONE)
|
||||
if (!myTextureEnv.IsNull())
|
||||
{
|
||||
myTextureEnv->Bind (theGlContext,
|
||||
GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
|
||||
@@ -2307,6 +2403,7 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte
|
||||
mySceneTransformTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
|
||||
myRaytraceMaterialTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
|
||||
myRaytraceLightSrcTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
|
||||
myRaytraceClippingTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceClippingTexture);
|
||||
|
||||
if (!myOpenGlFBO.IsNull())
|
||||
{
|
||||
@@ -2331,6 +2428,7 @@ void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlCon
|
||||
mySceneTransformTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
|
||||
myRaytraceMaterialTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
|
||||
myRaytraceLightSrcTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
|
||||
myRaytraceClippingTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceClippingTexture);
|
||||
|
||||
if (!myOpenGlFBO.IsNull())
|
||||
{
|
||||
@@ -2396,16 +2494,54 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
|
||||
myRNG.SetSeed();
|
||||
}
|
||||
|
||||
// Set frame accumulation weight
|
||||
myRaytraceProgram->SetUniform (theGlContext,
|
||||
myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
|
||||
myUniformLocations[0][OpenGl_RT_uMaxRadiance], static_cast<Standard_ShortReal> (myRenderParams.RadianceClampValue));
|
||||
|
||||
// Set random number generator seed
|
||||
myRaytraceProgram->SetUniform (theGlContext,
|
||||
myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
|
||||
}
|
||||
|
||||
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
Standard_Integer aSamplesPerPixel = myRenderParams.SamplesPerPixel;
|
||||
|
||||
if (aSamplesPerPixel == 0)
|
||||
{
|
||||
// Set frame accumulation weight
|
||||
myRaytraceProgram->SetUniform (theGlContext,
|
||||
myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
|
||||
|
||||
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int aPassIndex = 0; aPassIndex < aSamplesPerPixel; ++aPassIndex)
|
||||
{
|
||||
aRenderFramebuffer = (myAccumFrames + aPassIndex) % 2 ? myRaytraceFBO1[aFBOIdx] : myRaytraceFBO2[aFBOIdx];
|
||||
anAccumFramebuffer = (myAccumFrames + aPassIndex) % 2 ? myRaytraceFBO2[aFBOIdx] : myRaytraceFBO1[aFBOIdx];
|
||||
|
||||
aRenderFramebuffer->BindBuffer (theGlContext);
|
||||
|
||||
anAccumFramebuffer->ColorTexture()->Bind (
|
||||
theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
|
||||
|
||||
// Set frame accumulation weight
|
||||
myRaytraceProgram->SetUniform (theGlContext,
|
||||
myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + aPassIndex + 1));
|
||||
|
||||
// Set random number generator seed
|
||||
myRaytraceProgram->SetUniform (theGlContext,
|
||||
myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
|
||||
|
||||
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
//++myAccumFrames;
|
||||
glFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
++myAccumFrames;
|
||||
}
|
||||
|
||||
if (myRaytraceParameters.GlobalIllumination)
|
||||
{
|
||||
@@ -2427,6 +2563,9 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
|
||||
aRenderFramebuffer->DepthStencilTexture()->Bind (
|
||||
theGlContext, GL_TEXTURE0 + OpenGl_RT_DepthTexture);
|
||||
|
||||
myOutImageProgram->SetUniform (theGlContext,
|
||||
myUniformLocations[0][OpenGl_RT_uBilateralEnabled], myRenderParams.IsGIFilteringEnabled ? 1 : 0);
|
||||
|
||||
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
|
||||
aRenderFramebuffer->DepthStencilTexture()->Unbind (
|
||||
|
@@ -475,7 +475,7 @@ void OpenGl_View::Redraw()
|
||||
if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
|
||||
&& myRenderParams.IsGlobalIlluminationEnabled)
|
||||
{
|
||||
myAccumFrames++;
|
||||
myAccumFrames += myRenderParams.SamplesPerPixel;
|
||||
}
|
||||
|
||||
// bind default FBO
|
||||
@@ -1137,7 +1137,15 @@ void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
|
||||
// display global trihedron
|
||||
if (myToShowTrihedron)
|
||||
{
|
||||
// disable environment texture
|
||||
Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
|
||||
Handle(OpenGl_Texture) anEmptyTexture;
|
||||
theWorkspace->SetEnvironmentTexture (anEmptyTexture);
|
||||
|
||||
myTrihedron.Render (theWorkspace);
|
||||
|
||||
// restore environment texture
|
||||
theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
|
||||
}
|
||||
if (myToShowGradTrihedron)
|
||||
{
|
||||
@@ -1284,84 +1292,50 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
|
||||
// Clear status bitfields
|
||||
myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
|
||||
|
||||
// Update state of surface detail level
|
||||
myWorkspace->GetGlContext()->ShaderManager()->UpdateSurfaceDetailStateTo (mySurfaceDetail);
|
||||
// First pass
|
||||
myWorkspace->SetEnvironmentTexture (myTextureEnv);
|
||||
renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
|
||||
myWorkspace->DisableTexture();
|
||||
|
||||
// Added PCT for handling of textures
|
||||
switch (mySurfaceDetail)
|
||||
// Second pass
|
||||
if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
|
||||
{
|
||||
case Graphic3d_TOD_NONE:
|
||||
myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
|
||||
myWorkspace->DisableTexture();
|
||||
// Render the view
|
||||
renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
|
||||
break;
|
||||
myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
|
||||
|
||||
case Graphic3d_TOD_ENVIRONMENT:
|
||||
myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
|
||||
if (myRenderParams.Method != Graphic3d_RM_RAYTRACING)
|
||||
{
|
||||
myWorkspace->EnableTexture (myTextureEnv);
|
||||
}
|
||||
// Render the view
|
||||
renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
|
||||
myWorkspace->DisableTexture();
|
||||
break;
|
||||
// Remember OpenGl properties
|
||||
GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA;
|
||||
GLint aSaveZbuffFunc;
|
||||
GLboolean aSaveZbuffWrite;
|
||||
glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
|
||||
glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
|
||||
glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
|
||||
#endif
|
||||
GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
|
||||
GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
|
||||
|
||||
case Graphic3d_TOD_ALL:
|
||||
// First pass
|
||||
myWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
|
||||
// Render the view
|
||||
renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
|
||||
myWorkspace->DisableTexture();
|
||||
// Change the properties for second rendering pass
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
// Second pass
|
||||
if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
|
||||
{
|
||||
myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
|
||||
if (myRenderParams.Method != Graphic3d_RM_RAYTRACING)
|
||||
{
|
||||
myWorkspace->EnableTexture (myTextureEnv);
|
||||
}
|
||||
glDepthFunc (GL_EQUAL);
|
||||
glDepthMask (GL_FALSE);
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
|
||||
// Remember OpenGl properties
|
||||
GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA;
|
||||
GLint aSaveZbuffFunc;
|
||||
GLboolean aSaveZbuffWrite;
|
||||
glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
|
||||
glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
|
||||
glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
|
||||
#endif
|
||||
GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
|
||||
GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
|
||||
// Render the view
|
||||
renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
|
||||
myWorkspace->DisableTexture();
|
||||
|
||||
// Change the properties for second rendering pass
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable (GL_BLEND);
|
||||
// Restore properties back
|
||||
glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
|
||||
if (!wasBlendEnabled)
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
glDepthFunc (GL_EQUAL);
|
||||
glDepthMask (GL_FALSE);
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
|
||||
myWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
|
||||
|
||||
// Render the view
|
||||
renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
|
||||
myWorkspace->DisableTexture();
|
||||
|
||||
// Restore properties back
|
||||
glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
|
||||
if (!wasBlendEnabled)
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
glDepthFunc (aSaveZbuffFunc);
|
||||
glDepthMask (aSaveZbuffWrite);
|
||||
if (!wasZbuffEnabled)
|
||||
glDisable (GL_DEPTH_FUNC);
|
||||
}
|
||||
break;
|
||||
glDepthFunc (aSaveZbuffFunc);
|
||||
glDepthMask (aSaveZbuffWrite);
|
||||
if (!wasZbuffEnabled)
|
||||
glDisable (GL_DEPTH_FUNC);
|
||||
}
|
||||
|
||||
// Apply restored view matrix.
|
||||
|
@@ -970,12 +970,17 @@ const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean th
|
||||
updateMaterial (TEL_BACK_MATERIAL);
|
||||
}
|
||||
|
||||
if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
|
||||
if (AspectFace_set->DoTextureMap())
|
||||
{
|
||||
if (AspectFace_set->DoTextureMap())
|
||||
EnableTexture (AspectFace_set->TextureRes (myGlContext),
|
||||
AspectFace_set->TextureParams());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!myEnvironmentTexture.IsNull())
|
||||
{
|
||||
EnableTexture (AspectFace_set->TextureRes (myGlContext),
|
||||
AspectFace_set->TextureParams());
|
||||
EnableTexture (myEnvironmentTexture,
|
||||
myEnvironmentTexture->GetParams());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -236,6 +236,18 @@ public:
|
||||
return myFrontCulling;
|
||||
}
|
||||
|
||||
//! Sets a new environment texture.
|
||||
void SetEnvironmentTexture (const Handle(OpenGl_Texture)& theTexture)
|
||||
{
|
||||
myEnvironmentTexture = theTexture;
|
||||
}
|
||||
|
||||
//! Returns environment texture.
|
||||
const Handle(OpenGl_Texture)& EnvironmentTexture() const
|
||||
{
|
||||
return myEnvironmentTexture;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void updateMaterial (const int theFlag);
|
||||
@@ -281,6 +293,8 @@ protected: //! @name fields related to status
|
||||
|
||||
OpenGl_AspectFace myAspectFaceHl; //!< Hiddenline aspect
|
||||
|
||||
Handle(OpenGl_Texture) myEnvironmentTexture;
|
||||
|
||||
public: //! @name type definition
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient)
|
||||
|
@@ -546,10 +546,6 @@ static Standard_Integer OCC280 (Draw_Interpretor& di, Standard_Integer argc, con
|
||||
|
||||
TCollection_AsciiString anOldName = ViewerTest::GetCurrentViewName();
|
||||
Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
|
||||
if (Draw::Atoi (argv[2]))
|
||||
{
|
||||
aViewer->SetDefaultSurfaceDetail (V3d_TEX_ALL);
|
||||
}
|
||||
aViewer->SetDefaultTypeOfView (V3d_PERSPECTIVE);
|
||||
Handle(Aspect_Window) asp = ViewerTest::CurrentView()->Window();
|
||||
Handle(V3d_View) aNewView = aViewer->CreateView();
|
||||
|
@@ -4,16 +4,59 @@ uniform sampler2D uInputTexture;
|
||||
//! Ray tracing depth image.
|
||||
uniform sampler2D uDepthTexture;
|
||||
|
||||
uniform int uBilateralEnabled;
|
||||
|
||||
//! Output pixel color.
|
||||
out vec4 OutColor;
|
||||
|
||||
const float rI = 0.270 * 1.0f; // The intensity radius (in pixels).
|
||||
const float rL = 1.71 * 0.5f; // The geometric radius (in pixels).
|
||||
const int WindowSize = 8; // The window size (in pixels).
|
||||
|
||||
float gaussian (float theL, float theR)
|
||||
{
|
||||
return exp (-theL * theL / (2.0f * theR * theR));
|
||||
}
|
||||
|
||||
vec4 bilateral()
|
||||
{
|
||||
// Get the sizes
|
||||
int aWindow = WindowSize / 2;
|
||||
vec4 anOutCol = vec4 (0.f, 0.f, 0.f, 0.f);
|
||||
vec4 aRefCol = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
|
||||
float aNorm = 0.f;
|
||||
|
||||
// Compute the kernel
|
||||
for (int i = -aWindow; i <= aWindow; i++)
|
||||
{
|
||||
for (int j = -aWindow; j <= aWindow; j++)
|
||||
{
|
||||
vec4 aCol = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy) + ivec2 (j, i), 0);
|
||||
float A = gaussian (distance (aCol, aRefCol), rI);
|
||||
float B = gaussian (length (vec2(j, i)), rL);
|
||||
anOutCol += aCol * A * B;
|
||||
aNorm += A * B;
|
||||
}
|
||||
}
|
||||
return anOutCol * (1.f / aNorm);
|
||||
}
|
||||
|
||||
void main (void)
|
||||
{
|
||||
vec4 aColor = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
|
||||
vec4 aColor;
|
||||
|
||||
if (bool (uBilateralEnabled))
|
||||
{
|
||||
aColor = bilateral();
|
||||
}
|
||||
else
|
||||
{
|
||||
aColor = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
|
||||
}
|
||||
|
||||
float aDepth = texelFetch (uDepthTexture, ivec2 (gl_FragCoord.xy), 0).r;
|
||||
gl_FragDepth = aDepth;
|
||||
|
||||
// apply gamma correction (we use gamma = 2)
|
||||
OutColor = vec4 (sqrt (aColor.rgb), aColor.a);
|
||||
}
|
||||
}
|
@@ -247,7 +247,7 @@ void transmitted (in float theIndex, in vec3 theIncident, out vec3 theTransmit)
|
||||
//=======================================================================
|
||||
float handleLambertianReflection (in vec3 theInput, in vec3 theOutput)
|
||||
{
|
||||
return max (0.f, theInput.z) * (1.f / M_PI);
|
||||
return abs (theInput.z) * (1.f / M_PI);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -298,7 +298,7 @@ vec3 handleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFres
|
||||
vec3 handleMaterial (in SMaterial theMaterial, in vec3 theInput, in vec3 theOutput)
|
||||
{
|
||||
return theMaterial.Kd.rgb * handleLambertianReflection (theInput, theOutput) +
|
||||
theMaterial.Ks.rgb * handleBlinnReflection (theInput, theOutput, theMaterial.Fresnel, theMaterial.Ks.w);
|
||||
theMaterial.Ks.rgb * handleBlinnReflection (theInput, theOutput, theMaterial.Fresnel, theMaterial.Ks.w);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -698,10 +698,15 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
|
||||
aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),
|
||||
dot (aTrsfRow2, aTexCoord));
|
||||
|
||||
vec3 aTexColor = textureLod (
|
||||
sampler2D (uTextureSamplers[int (aMaterial.Kd.w)]), aTexCoord.st, 0.f).rgb;
|
||||
vec4 aTexColor = textureLod (
|
||||
sampler2D (uTextureSamplers[int (aMaterial.Kd.w)]), aTexCoord.st, 0.f);
|
||||
|
||||
aMaterial.Kd.rgb *= aTexColor;
|
||||
aMaterial.Kd.rgb *= aTexColor.rgb * aTexColor.a;
|
||||
|
||||
if (aTexColor.a < 1.f)
|
||||
{
|
||||
aMaterial.Kt = 0.8f * vec3 (1.f - aTexColor.a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -783,8 +788,8 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
|
||||
|
||||
anInput = normalize (fromLocalSpace (anInput, aSpace));
|
||||
|
||||
theRay = SRay (theRay.Origin + anInput * uSceneEpsilon +
|
||||
aHit.Normal * mix (-uSceneEpsilon, uSceneEpsilon, step (0.f, dot (aHit.Normal, anInput))), anInput);
|
||||
theRay = SRay (theRay.Origin + anInput * uSceneEpsilon, anInput);// +
|
||||
//aHit.Normal * mix (-uSceneEpsilon, uSceneEpsilon, step (0.f, dot (aHit.Normal, anInput))), anInput);
|
||||
|
||||
theInverse = InverseDirection (anInput);
|
||||
|
||||
|
@@ -63,6 +63,9 @@ uniform isamplerBuffer uGeometryTriangTexture;
|
||||
uniform samplerBuffer uRaytraceMaterialTexture;
|
||||
//! Texture buffer of light source properties.
|
||||
uniform samplerBuffer uRaytraceLightSrcTexture;
|
||||
//! Texture buffer of clipping planes properties.
|
||||
uniform samplerBuffer uRaytraceClippingTexture;
|
||||
|
||||
//! Environment map texture.
|
||||
uniform sampler2D uEnvironmentMapTexture;
|
||||
|
||||
@@ -378,12 +381,20 @@ struct SSubTree
|
||||
ivec4 SubData;
|
||||
};
|
||||
|
||||
#define EMPTY_ROOT ivec4(0)
|
||||
|
||||
#define TRS_OFFSET(treelet) treelet.SubData.x
|
||||
#define BVH_OFFSET(treelet) treelet.SubData.y
|
||||
#define VRT_OFFSET(treelet) treelet.SubData.z
|
||||
#define TRG_OFFSET(treelet) treelet.SubData.w
|
||||
|
||||
#define EMPTY_ROOT ivec4(0)
|
||||
#define MAX_CLIP_PLANES 1
|
||||
|
||||
#define IS_PLANE_ACTIVE(params) (params.x != -1.F)
|
||||
#define IS_PLANE_HIDDEN(params) (params.x == -1.F)
|
||||
|
||||
#define PLANE_SETTINGS(trsf, index) (16 * int(trsf.w) + 2 * index + 0)
|
||||
#define PLANE_EQUATION(trsf, index) (16 * int(trsf.w) + 2 * index + 1)
|
||||
|
||||
// =======================================================================
|
||||
// function : SceneNearestHit
|
||||
@@ -399,6 +410,9 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
|
||||
|
||||
SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
|
||||
|
||||
float aClipMax = MAXFLOAT;
|
||||
float aClipMin = -MAXFLOAT;
|
||||
|
||||
for (bool toContinue = true; toContinue;)
|
||||
{
|
||||
ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
|
||||
@@ -475,7 +489,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
|
||||
float aTime = IntersectTriangle (aSubTree.TrsfRay,
|
||||
aPoint0, aPoint1, aPoint2, aParams, aNormal);
|
||||
|
||||
if (aTime < theHit.Time)
|
||||
if (aTime > aClipMin && aTime < aClipMax && aTime < theHit.Time)
|
||||
{
|
||||
aTriIndex = aTriangle;
|
||||
|
||||
@@ -496,13 +510,34 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
|
||||
}
|
||||
else if (aData.x > 0) // switch node
|
||||
{
|
||||
aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root
|
||||
aClipMax = MAXFLOAT;
|
||||
aClipMin = -MAXFLOAT;
|
||||
|
||||
aSubTree.SubData = ivec4 (aData.x * 4 - 4, aData.yzw); // store BVH sub-root
|
||||
|
||||
vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);
|
||||
vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);
|
||||
vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);
|
||||
vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);
|
||||
|
||||
for (int aPlaneIdx = 0; aInvTransf3.w >= 0.0 && aPlaneIdx < MAX_CLIP_PLANES; ++aPlaneIdx)
|
||||
{
|
||||
vec4 aSettings = texelFetch (uRaytraceClippingTexture, PLANE_SETTINGS (aInvTransf3, aPlaneIdx));
|
||||
vec4 aEquation = texelFetch (uRaytraceClippingTexture, PLANE_EQUATION (aInvTransf3, aPlaneIdx));
|
||||
|
||||
float aNdotD = -dot (aEquation.xyz, theRay.Direct);
|
||||
|
||||
if (IS_PLANE_ACTIVE (aSettings))
|
||||
{
|
||||
float aPlaneTime = (dot (aEquation.xyz, theRay.Origin) + aEquation.w) / aNdotD;
|
||||
|
||||
if (aNdotD < 0.0)
|
||||
aClipMin = max (aClipMin, aPlaneTime);
|
||||
else
|
||||
aClipMax = min (aClipMax, aPlaneTime);
|
||||
}
|
||||
}
|
||||
|
||||
aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,
|
||||
aInvTransf0,
|
||||
aInvTransf1,
|
||||
@@ -540,6 +575,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
|
||||
|
||||
SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
|
||||
|
||||
float aClipMax = MAXFLOAT;
|
||||
float aClipMin = -MAXFLOAT;
|
||||
|
||||
for (bool toContinue = true; toContinue;)
|
||||
{
|
||||
ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
|
||||
@@ -617,12 +655,12 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
|
||||
aPoint0, aPoint1, aPoint2, aParams, aNormal);
|
||||
|
||||
#ifdef TRANSPARENT_SHADOWS
|
||||
if (aTime < theDistance)
|
||||
if (aTime > aClipMin && aTime < aClipMax && aTime < theDistance)
|
||||
{
|
||||
aFactor *= 1.f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x;
|
||||
}
|
||||
#else
|
||||
if (aTime < theDistance)
|
||||
if (aTime > aClipMin && aTime < aClipMax && aTime < theDistance)
|
||||
{
|
||||
aFactor = 0.f;
|
||||
}
|
||||
@@ -640,6 +678,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
|
||||
}
|
||||
else if (aData.x > 0) // switch node
|
||||
{
|
||||
aClipMax = MAXFLOAT;
|
||||
aClipMin = -MAXFLOAT;
|
||||
|
||||
aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root
|
||||
|
||||
vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);
|
||||
@@ -647,6 +688,24 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
|
||||
vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);
|
||||
vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);
|
||||
|
||||
for (int aPlaneIdx = 0; aInvTransf3.w >= 0.0 && aPlaneIdx < MAX_CLIP_PLANES; ++aPlaneIdx)
|
||||
{
|
||||
vec4 aSettings = texelFetch (uRaytraceClippingTexture, PLANE_SETTINGS (aInvTransf3, aPlaneIdx));
|
||||
vec4 aEquation = texelFetch (uRaytraceClippingTexture, PLANE_EQUATION (aInvTransf3, aPlaneIdx));
|
||||
|
||||
float aNdotD = -dot (aEquation.xyz, theRay.Direct);
|
||||
|
||||
if (IS_PLANE_ACTIVE (aSettings))
|
||||
{
|
||||
float aPlaneTime = (dot (aEquation.xyz, theRay.Origin) + aEquation.w) / aNdotD;
|
||||
|
||||
if (aNdotD < 0.0)
|
||||
aClipMin = max (aClipMin, aPlaneTime);
|
||||
else
|
||||
aClipMax = min (aClipMax, aPlaneTime);
|
||||
}
|
||||
}
|
||||
|
||||
aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,
|
||||
aInvTransf0,
|
||||
aInvTransf1,
|
||||
|
@@ -13,7 +13,8 @@ uniform sampler2D uAccumTexture;
|
||||
//! Increases performance up to 4 times, but noise becomes structured.
|
||||
uniform int uBlockedRngEnabled;
|
||||
|
||||
#define MAX_RADIANCE vec3 (10.f)
|
||||
//! Maximum value for radiance clamping.
|
||||
uniform float uMaxRadiance;
|
||||
|
||||
// =======================================================================
|
||||
// function : main
|
||||
@@ -46,7 +47,7 @@ void main (void)
|
||||
aColor.rgb = ZERO;
|
||||
}
|
||||
|
||||
aColor.rgb = min (aColor.rgb, MAX_RADIANCE);
|
||||
aColor.rgb = min (aColor.rgb, vec3 (uMaxRadiance));
|
||||
|
||||
OutColor = mix (texture2D (uAccumTexture, vPixel), aColor, uSampleWeight);
|
||||
#else
|
||||
|
@@ -4,3 +4,5 @@ TKService
|
||||
TKernel
|
||||
TKG3d
|
||||
TKG2d
|
||||
TKXCAF
|
||||
TKLCAF
|
@@ -1,4 +1,6 @@
|
||||
TKGeomBase
|
||||
TKXCAF
|
||||
TKLCAF
|
||||
TKFillet
|
||||
TKBRep
|
||||
TKTopAlgo
|
||||
@@ -15,6 +17,7 @@ TKTopTest
|
||||
TKG3d
|
||||
TKOffset
|
||||
TKMesh
|
||||
TKMeshVS
|
||||
TKV3d
|
||||
TKDraw
|
||||
TKOpenGl
|
||||
|
@@ -31,7 +31,6 @@ V3d_TypeOfPickCamera.hxx
|
||||
V3d_TypeOfPickLight.hxx
|
||||
V3d_TypeOfRepresentation.hxx
|
||||
V3d_TypeOfShadingModel.hxx
|
||||
V3d_TypeOfSurfaceDetail.hxx
|
||||
V3d_TypeOfUpdate.hxx
|
||||
V3d_TypeOfView.hxx
|
||||
V3d_TypeOfVisualization.hxx
|
||||
|
@@ -1,31 +0,0 @@
|
||||
// Created on: 1992-11-13
|
||||
// Created by: GG
|
||||
// Copyright (c) 1992-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _V3d_TypeOfSurfaceDetail_HeaderFile
|
||||
#define _V3d_TypeOfSurfaceDetail_HeaderFile
|
||||
|
||||
//! Modes of visualization for objects in a view
|
||||
//! - V3d_TEX_NONE: no texture mapping,
|
||||
//! - V3d_TEX_ENVIRONMENT: environment mapping only,
|
||||
//! - V3d_TEX_ALL: environment and texture mapping.
|
||||
enum V3d_TypeOfSurfaceDetail
|
||||
{
|
||||
V3d_TEX_NONE,
|
||||
V3d_TEX_ENVIRONMENT,
|
||||
V3d_TEX_ALL
|
||||
};
|
||||
|
||||
#endif // _V3d_TypeOfSurfaceDetail_HeaderFile
|
@@ -159,7 +159,6 @@ V3d_View::V3d_View (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView th
|
||||
SetAxis (0.,0.,0.,1.,1.,1.);
|
||||
SetVisualization (theViewer->DefaultVisualization());
|
||||
SetShadingModel (theViewer->DefaultShadingModel());
|
||||
SetSurfaceDetail (theViewer->DefaultSurfaceDetail());
|
||||
SetTwist (0.);
|
||||
SetAt (0.,0.,0.);
|
||||
SetProj (theViewer->DefaultViewProj());
|
||||
@@ -625,15 +624,6 @@ void V3d_View::SetShadingModel (const V3d_TypeOfShadingModel theShadingModel)
|
||||
myView->SetShadingModel (static_cast<Graphic3d_TypeOfShadingModel> (theShadingModel));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//function : SetSurfaceDetail
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void V3d_View::SetSurfaceDetail (const V3d_TypeOfSurfaceDetail theSurfaceDetail)
|
||||
{
|
||||
myView->SetSurfaceDetailType (static_cast<Graphic3d_TypeOfSurfaceDetail> (theSurfaceDetail));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//function : SetTextureEnv
|
||||
//purpose :
|
||||
@@ -2421,15 +2411,6 @@ V3d_TypeOfShadingModel V3d_View::ShadingModel() const
|
||||
return static_cast<V3d_TypeOfShadingModel> (myView->ShadingModel());
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//function : SurfaceDetail
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
V3d_TypeOfSurfaceDetail V3d_View::SurfaceDetail() const
|
||||
{
|
||||
return static_cast<V3d_TypeOfSurfaceDetail> (myView->SurfaceDetailType());
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//function : TextureEnv
|
||||
//purpose :
|
||||
|
@@ -75,7 +75,6 @@
|
||||
#include <V3d_TypeOfBackfacingModel.hxx>
|
||||
#include <V3d_TypeOfOrientation.hxx>
|
||||
#include <V3d_TypeOfShadingModel.hxx>
|
||||
#include <V3d_TypeOfSurfaceDetail.hxx>
|
||||
#include <V3d_TypeOfView.hxx>
|
||||
#include <V3d_TypeOfVisualization.hxx>
|
||||
#include <V3d_TypeOfZclipping.hxx>
|
||||
@@ -260,9 +259,6 @@ public:
|
||||
//! Defines the shading model for the visualization. Various models are available.
|
||||
Standard_EXPORT void SetShadingModel (const V3d_TypeOfShadingModel theShadingModel);
|
||||
|
||||
//! Selects the kind of rendering for texture mapping. No texture mapping by default.
|
||||
Standard_EXPORT void SetSurfaceDetail (const V3d_TypeOfSurfaceDetail theSurfaceDetail);
|
||||
|
||||
//! Sets the environment texture to use. No environment texture by default.
|
||||
Standard_EXPORT void SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTexture);
|
||||
|
||||
@@ -721,8 +717,6 @@ public:
|
||||
//! Returns the current shading model.
|
||||
Standard_EXPORT V3d_TypeOfShadingModel ShadingModel() const;
|
||||
|
||||
Standard_EXPORT V3d_TypeOfSurfaceDetail SurfaceDetail() const;
|
||||
|
||||
Standard_EXPORT Handle(Graphic3d_TextureEnv) TextureEnv() const;
|
||||
|
||||
//! Returns the current visualisation mode.
|
||||
|
@@ -48,8 +48,7 @@ V3d_Viewer::V3d_Viewer (const Handle(Graphic3d_GraphicDriver)& theDriver,
|
||||
const V3d_TypeOfShadingModel theShadingModel,
|
||||
const V3d_TypeOfUpdate theUpdateMode,
|
||||
const Standard_Boolean theComputedMode,
|
||||
const Standard_Boolean theDefaultComputedMode,
|
||||
const V3d_TypeOfSurfaceDetail theSurfaceDetail)
|
||||
const Standard_Boolean theDefaultComputedMode)
|
||||
:myNextCount (-1),
|
||||
myDriver (theDriver),
|
||||
myName (TCollection_ExtendedString (theName)),
|
||||
@@ -78,7 +77,6 @@ myZLayerGenId (1, IntegerLast())
|
||||
SetDefaultBackgroundColor (theViewBackground);
|
||||
SetDefaultVisualization (theVisualization);
|
||||
SetDefaultShadingModel (theShadingModel);
|
||||
SetDefaultSurfaceDetail (theSurfaceDetail);
|
||||
SetDefaultAngle (M_PI / 2.);
|
||||
SetDefaultTypeOfView (V3d_ORTHOGRAPHIC);
|
||||
|
||||
@@ -319,11 +317,6 @@ void V3d_Viewer::SetDefaultShadingModel(const V3d_TypeOfShadingModel Type) {
|
||||
MyShadingModel = Type ;
|
||||
}
|
||||
|
||||
void V3d_Viewer::SetDefaultSurfaceDetail(const V3d_TypeOfSurfaceDetail Type) {
|
||||
|
||||
MySurfaceDetail = Type ;
|
||||
}
|
||||
|
||||
void V3d_Viewer::SetDefaultAngle(const Quantity_PlaneAngle Angle) {
|
||||
MyDefaultAngle = Angle;
|
||||
}
|
||||
@@ -372,10 +365,6 @@ V3d_TypeOfShadingModel V3d_Viewer::DefaultShadingModel() const {
|
||||
return MyShadingModel ;
|
||||
}
|
||||
|
||||
V3d_TypeOfSurfaceDetail V3d_Viewer::DefaultSurfaceDetail() const {
|
||||
return MySurfaceDetail ;
|
||||
}
|
||||
|
||||
Quantity_PlaneAngle V3d_Viewer::DefaultAngle() const {
|
||||
return MyDefaultAngle;
|
||||
}
|
||||
|
@@ -48,7 +48,6 @@
|
||||
#include <V3d_ListOfTransient.hxx>
|
||||
#include <V3d_TypeOfOrientation.hxx>
|
||||
#include <V3d_TypeOfShadingModel.hxx>
|
||||
#include <V3d_TypeOfSurfaceDetail.hxx>
|
||||
#include <V3d_TypeOfUpdate.hxx>
|
||||
#include <V3d_TypeOfView.hxx>
|
||||
#include <V3d_TypeOfVisualization.hxx>
|
||||
@@ -91,7 +90,7 @@ public:
|
||||
//! This limitation might be addressed in some future OCCT releases.
|
||||
//! If the size of the view is <= 0
|
||||
//! Warning: Client must creates a graphic driver
|
||||
Standard_EXPORT V3d_Viewer(const Handle(Graphic3d_GraphicDriver)& theDriver, const Standard_ExtString theName, const Standard_CString theDomain = "", const Quantity_Length theViewSize = 1000.0, const V3d_TypeOfOrientation theViewProj = V3d_XposYnegZpos, const Quantity_NameOfColor theViewBackground = Quantity_NOC_GRAY30, const V3d_TypeOfVisualization theVisualization = V3d_ZBUFFER, const V3d_TypeOfShadingModel theShadingModel = V3d_GOURAUD, const V3d_TypeOfUpdate theUpdateMode = V3d_WAIT, const Standard_Boolean theComputedMode = Standard_True, const Standard_Boolean theDefaultComputedMode = Standard_True, const V3d_TypeOfSurfaceDetail theSurfaceDetail = V3d_TEX_NONE);
|
||||
Standard_EXPORT V3d_Viewer(const Handle(Graphic3d_GraphicDriver)& theDriver, const Standard_ExtString theName, const Standard_CString theDomain = "", const Quantity_Length theViewSize = 1000.0, const V3d_TypeOfOrientation theViewProj = V3d_XposYnegZpos, const Quantity_NameOfColor theViewBackground = Quantity_NOC_GRAY30, const V3d_TypeOfVisualization theVisualization = V3d_ZBUFFER, const V3d_TypeOfShadingModel theShadingModel = V3d_GOURAUD, const V3d_TypeOfUpdate theUpdateMode = V3d_WAIT, const Standard_Boolean theComputedMode = Standard_True, const Standard_Boolean theDefaultComputedMode = Standard_True);
|
||||
|
||||
//! creates a view in the viewer according to its
|
||||
//! default parameters.
|
||||
@@ -179,9 +178,6 @@ public:
|
||||
//! Gives the default type of SHADING.
|
||||
Standard_EXPORT void SetDefaultShadingModel (const V3d_TypeOfShadingModel Type);
|
||||
|
||||
//! Gives the default type of texture mapping.
|
||||
Standard_EXPORT void SetDefaultSurfaceDetail (const V3d_TypeOfSurfaceDetail Type);
|
||||
|
||||
Standard_EXPORT void SetDefaultAngle (const Quantity_PlaneAngle Angle);
|
||||
|
||||
//! Defines the mode of regenerating the views making
|
||||
@@ -240,9 +236,6 @@ public:
|
||||
//! Returns the default type of Shading
|
||||
Standard_EXPORT V3d_TypeOfShadingModel DefaultShadingModel() const;
|
||||
|
||||
//! Returns the default type of texture mapping
|
||||
Standard_EXPORT V3d_TypeOfSurfaceDetail DefaultSurfaceDetail() const;
|
||||
|
||||
Standard_EXPORT Quantity_PlaneAngle DefaultAngle() const;
|
||||
|
||||
//! Returns the regeneration mode of views in the viewer.
|
||||
@@ -489,7 +482,6 @@ private:
|
||||
V3d_TypeOfOrientation MyViewProj;
|
||||
V3d_TypeOfVisualization MyVisualization;
|
||||
V3d_TypeOfShadingModel MyShadingModel;
|
||||
V3d_TypeOfSurfaceDetail MySurfaceDetail;
|
||||
Quantity_PlaneAngle MyDefaultAngle;
|
||||
V3d_TypeOfView MyDefaultTypeOfView;
|
||||
Graphic3d_RenderingParams myDefaultRenderingParams;
|
||||
|
@@ -3201,8 +3201,6 @@ Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb,
|
||||
|
||||
Standard_Integer aPreviousMode = 0;
|
||||
|
||||
ViewerTest::CurrentView()->SetSurfaceDetail (V3d_TEX_ALL);
|
||||
|
||||
TCollection_AsciiString aShapeName (theArgv[1]);
|
||||
Handle(AIS_InteractiveObject) anIO;
|
||||
|
||||
@@ -3898,125 +3896,6 @@ static int VPerf(Draw_Interpretor& di, Standard_Integer , const char** argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//==================================================================================
|
||||
// Function : VAnimation
|
||||
//==================================================================================
|
||||
static int VAnimation (Draw_Interpretor& di, Standard_Integer argc, const char** argv) {
|
||||
if (argc != 5) {
|
||||
di<<"Use: "<<argv[0]<<" CrankArmFile CylinderHeadFile PropellerFile EngineBlockFile\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Standard_Real thread = 4;
|
||||
Standard_Real angleA=0;
|
||||
Standard_Real angleB;
|
||||
Standard_Real X;
|
||||
gp_Ax1 Ax1(gp_Pnt(0,0,0),gp_Vec(0,0,1));
|
||||
|
||||
BRep_Builder B;
|
||||
TopoDS_Shape CrankArm;
|
||||
TopoDS_Shape CylinderHead;
|
||||
TopoDS_Shape Propeller;
|
||||
TopoDS_Shape EngineBlock;
|
||||
|
||||
//BRepTools::Read(CrankArm,"/dp_26/Indus/ege/assemblage/CrankArm.rle",B);
|
||||
//BRepTools::Read(CylinderHead,"/dp_26/Indus/ege/assemblage/CylinderHead.rle",B);
|
||||
//BRepTools::Read(Propeller,"/dp_26/Indus/ege/assemblage/Propeller.rle",B);
|
||||
//BRepTools::Read(EngineBlock,"/dp_26/Indus/ege/assemblage/EngineBlock.rle",B);
|
||||
BRepTools::Read(CrankArm,argv[1],B);
|
||||
BRepTools::Read(CylinderHead,argv[2],B);
|
||||
BRepTools::Read(Propeller,argv[3],B);
|
||||
BRepTools::Read(EngineBlock,argv[4],B);
|
||||
|
||||
if (CrankArm.IsNull() || CylinderHead.IsNull() || Propeller.IsNull() || EngineBlock.IsNull()) {di<<" Syntaxe error:loading failure.\n";}
|
||||
|
||||
|
||||
OSD_Timer myTimer;
|
||||
myTimer.Start();
|
||||
|
||||
Handle(AIS_Shape) myAisCylinderHead = new AIS_Shape (CylinderHead);
|
||||
Handle(AIS_Shape) myAisEngineBlock = new AIS_Shape (EngineBlock);
|
||||
Handle(AIS_Shape) myAisCrankArm = new AIS_Shape (CrankArm);
|
||||
Handle(AIS_Shape) myAisPropeller = new AIS_Shape (Propeller);
|
||||
|
||||
GetMapOfAIS().Bind(myAisCylinderHead,"a");
|
||||
GetMapOfAIS().Bind(myAisEngineBlock,"b");
|
||||
GetMapOfAIS().Bind(myAisCrankArm,"c");
|
||||
GetMapOfAIS().Bind(myAisPropeller,"d");
|
||||
|
||||
myAisCylinderHead->SetMutable (Standard_True);
|
||||
myAisEngineBlock ->SetMutable (Standard_True);
|
||||
myAisCrankArm ->SetMutable (Standard_True);
|
||||
myAisPropeller ->SetMutable (Standard_True);
|
||||
|
||||
TheAISContext()->SetColor (myAisCylinderHead, Quantity_NOC_INDIANRED);
|
||||
TheAISContext()->SetColor (myAisEngineBlock, Quantity_NOC_RED);
|
||||
TheAISContext()->SetColor (myAisPropeller, Quantity_NOC_GREEN);
|
||||
|
||||
TheAISContext()->Display (myAisCylinderHead, Standard_False);
|
||||
TheAISContext()->Display (myAisEngineBlock, Standard_False);
|
||||
TheAISContext()->Display (myAisCrankArm, Standard_False);
|
||||
TheAISContext()->Display (myAisPropeller, Standard_False);
|
||||
|
||||
TheAISContext()->Deactivate(myAisCylinderHead);
|
||||
TheAISContext()->Deactivate(myAisEngineBlock );
|
||||
TheAISContext()->Deactivate(myAisCrankArm );
|
||||
TheAISContext()->Deactivate(myAisPropeller );
|
||||
|
||||
// Boucle de mouvement
|
||||
for (Standard_Real myAngle = 0;angleA<2*M_PI*10.175 ;myAngle++) {
|
||||
|
||||
angleA = thread*myAngle*M_PI/180;
|
||||
X = Sin(angleA)*3/8;
|
||||
angleB = atan(X / Sqrt(-X * X + 1));
|
||||
Standard_Real decal(25*0.6);
|
||||
|
||||
|
||||
//Build a transformation on the display
|
||||
gp_Trsf aPropellerTrsf;
|
||||
aPropellerTrsf.SetRotation(Ax1,angleA);
|
||||
TheAISContext()->SetLocation(myAisPropeller,aPropellerTrsf);
|
||||
|
||||
gp_Ax3 base(gp_Pnt(3*decal*(1-Cos(angleA)),-3*decal*Sin(angleA),0),gp_Vec(0,0,1),gp_Vec(1,0,0));
|
||||
gp_Trsf aCrankArmTrsf;
|
||||
aCrankArmTrsf.SetTransformation( base.Rotated(gp_Ax1(gp_Pnt(3*decal,0,0),gp_Dir(0,0,1)),angleB));
|
||||
TheAISContext()->SetLocation(myAisCrankArm,aCrankArmTrsf);
|
||||
|
||||
TheAISContext()->UpdateCurrentViewer();
|
||||
}
|
||||
|
||||
TopoDS_Shape myNewCrankArm =myAisCrankArm ->Shape().Located( myAisCrankArm ->Transformation() );
|
||||
TopoDS_Shape myNewPropeller =myAisPropeller->Shape().Located( myAisPropeller->Transformation() );
|
||||
|
||||
myAisCrankArm ->ResetTransformation();
|
||||
myAisPropeller->ResetTransformation();
|
||||
|
||||
myAisCrankArm -> Set(myNewCrankArm );
|
||||
myAisPropeller -> Set(myNewPropeller);
|
||||
|
||||
TheAISContext()->Activate(myAisCylinderHead,0);
|
||||
TheAISContext()->Activate(myAisEngineBlock,0 );
|
||||
TheAISContext()->Activate(myAisCrankArm ,0 );
|
||||
TheAISContext()->Activate(myAisPropeller ,0 );
|
||||
|
||||
myTimer.Stop();
|
||||
myTimer.Show();
|
||||
myTimer.Start();
|
||||
|
||||
TheAISContext()->Redisplay(myAisCrankArm ,Standard_False);
|
||||
TheAISContext()->Redisplay(myAisPropeller,Standard_False);
|
||||
|
||||
TheAISContext()->UpdateCurrentViewer();
|
||||
a3DView()->Redraw();
|
||||
|
||||
myTimer.Stop();
|
||||
myTimer.Show();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : VShading
|
||||
//purpose : Sharpen or roughten the quality of the shading
|
||||
@@ -5148,6 +5027,9 @@ static Standard_Integer vr(Draw_Interpretor& , Standard_Integer , const char** a
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <MeshPresentation.h>
|
||||
#include <MeshVS_Drawer.hxx>
|
||||
#include <MeshVS_DrawerAttribute.hxx>
|
||||
//===============================================================================================
|
||||
//function : VBsdf
|
||||
//purpose :
|
||||
@@ -5203,7 +5085,17 @@ static int VBsdf (Draw_Interpretor& theDi,
|
||||
}
|
||||
|
||||
Handle(AIS_InteractiveObject) anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
|
||||
Graphic3d_MaterialAspect aMaterial = anIObj->Attributes()->ShadingAspect()->Material();
|
||||
Graphic3d_MaterialAspect aMaterial;
|
||||
|
||||
Handle(MeshPresentation) aMeshPrs = Handle(MeshPresentation)::DownCast (anIObj);
|
||||
if (aMeshPrs.IsNull())
|
||||
{
|
||||
aMaterial = anIObj->Attributes()->ShadingAspect()->Material();
|
||||
}
|
||||
else
|
||||
{
|
||||
aMeshPrs->GetDrawer()->GetMaterial(MeshVS_DA_FrontMaterial, aMaterial);
|
||||
}
|
||||
Graphic3d_BSDF aBSDF = aMaterial.BSDF();
|
||||
|
||||
if (aCmd.HasOption ("print"))
|
||||
@@ -5507,6 +5399,283 @@ static int VAutoActivateSelection (Draw_Interpretor& theDi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <ObjDataSource.h>
|
||||
#include <MeshPresentation.h>
|
||||
#include <MeshVS_Drawer.hxx>
|
||||
#include <MeshPrsBuilder.h>
|
||||
#include <MeshVS_MeshPrsBuilder.hxx>
|
||||
#include <MeshVS_DrawerAttribute.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
namespace
|
||||
{
|
||||
std::vector<TCollection_AsciiString> Split (const TCollection_AsciiString& pSource,
|
||||
const TCollection_AsciiString& pSeparator)
|
||||
{
|
||||
std::vector<TCollection_AsciiString> result;
|
||||
|
||||
TCollection_AsciiString token;
|
||||
const Standard_Integer aSize = pSource.Length();
|
||||
unsigned int previousPos = 1;
|
||||
unsigned int currentPos = 1;
|
||||
while ((currentPos = pSource.FirstLocationInSet(pSeparator, currentPos, aSize)) != 0)
|
||||
{
|
||||
result.push_back(pSource.SubString(previousPos, currentPos - previousPos));
|
||||
|
||||
previousPos = ++currentPos;
|
||||
}
|
||||
|
||||
// Save last element.
|
||||
result.push_back(pSource.SubString(previousPos, aSize));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Returns true for grayscale properties.
|
||||
inline bool isGrayscaleProperty (const TCollection_AsciiString& theName)
|
||||
{
|
||||
return theName == "intensity";
|
||||
}
|
||||
|
||||
Handle(MeshPresentation) createMeshPresentation (const Handle(MeshDataSource)& theDataSource,
|
||||
const TCollection_AsciiString& theEntry,
|
||||
TCollection_AsciiString& theSelEntry,
|
||||
Handle(MeshScalarProperty)& theSelProperty)
|
||||
{
|
||||
theSelEntry.Clear();
|
||||
theSelProperty.Nullify();
|
||||
if (theDataSource.IsNull())
|
||||
{
|
||||
return Handle(MeshPresentation)();
|
||||
}
|
||||
|
||||
theSelEntry = theEntry;
|
||||
if (theEntry.IsEmpty())
|
||||
{
|
||||
if (theDataSource->HasTexture())
|
||||
{
|
||||
theSelEntry = "ply_textured";
|
||||
}
|
||||
else if (theDataSource->HasNodalColors())
|
||||
{
|
||||
theSelEntry = "ply_colored";
|
||||
}
|
||||
/*else if (theDataSource->HasNormals())
|
||||
{
|
||||
theSelEntry = "ply_smoothshaded";
|
||||
}*/
|
||||
else
|
||||
{
|
||||
theSelEntry = "ply_smoothshaded";
|
||||
//theSelEntry = "ply_shaded";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << theSelEntry << std::endl;
|
||||
|
||||
Handle(MeshPresentation) aMesh = new MeshPresentation();
|
||||
Handle(MeshVS_Drawer) aDrawer = aMesh->GetDrawer();
|
||||
aDrawer->SetBoolean(MeshVS_DA_ShowEdges, Standard_False);
|
||||
aDrawer->SetBoolean(MeshVS_DA_SmoothShading, theDataSource->HasNormals());
|
||||
aMesh->SetDataSource(theDataSource);
|
||||
aMesh->SetMaterial(Graphic3d_NOM_PLASTIC); // myMatAspect
|
||||
if (theSelEntry == "ply_textured")
|
||||
{
|
||||
//myPrsCaps |= DisplayCaps_Texture;
|
||||
aDrawer->SetBoolean(MeshVS_DA_SmoothShading, Standard_True);
|
||||
aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
|
||||
Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_Shading);
|
||||
aBuilder->SetMapTextures(Standard_True);
|
||||
aMesh->AddBuilder(aBuilder, Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_Shading);
|
||||
}
|
||||
else if (theSelEntry == "ply_colored")
|
||||
{
|
||||
//myPrsCaps |= DisplayCaps_VertColor;
|
||||
aDrawer->SetBoolean(MeshVS_DA_ColorReflection, Standard_True);
|
||||
|
||||
Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder(aMesh, MeshVS_DMF_NodalColorDataPrs);
|
||||
theDataSource->FillNodalColorsBuilder(aBuilder);
|
||||
aMesh->AddBuilder(aBuilder, Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_NodalColorDataPrs);
|
||||
}
|
||||
else if (theSelEntry == "ply_wireframe")
|
||||
{
|
||||
aMesh->AddBuilder(new MeshVS_MeshPrsBuilder(aMesh.operator->()), Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_WireFrame);
|
||||
}
|
||||
else if (theSelEntry == "ply_smoothshaded")
|
||||
{
|
||||
aDrawer->SetBoolean(MeshVS_DA_SmoothShading, Standard_True);
|
||||
aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
|
||||
Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_Shading);
|
||||
aBuilder->SetMapTextures(Standard_False);
|
||||
aMesh->AddBuilder(aBuilder, Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_Shading);
|
||||
}
|
||||
else if (theSelEntry == "ply_shaded")
|
||||
{
|
||||
aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
|
||||
aDrawer->SetBoolean(MeshVS_DA_SmoothShading, Standard_False);
|
||||
aMesh->AddBuilder(new MeshVS_MeshPrsBuilder(aMesh.operator->()), Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_Shading);
|
||||
}
|
||||
else if (theSelEntry == "ply_shrink")
|
||||
{
|
||||
aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
|
||||
aMesh->AddBuilder(new MeshVS_MeshPrsBuilder(aMesh.operator->()), Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_Shrink);
|
||||
}
|
||||
//else if (theSelEntry.startsWith("ply_group_nodalprops\n"))
|
||||
else if (theSelEntry.Search("ply_group_nodalprops\n") != -1)
|
||||
{
|
||||
//myPrsCaps |= DisplayCaps_Texture;
|
||||
std::vector<TCollection_AsciiString> aList = Split(theEntry, "\n");
|
||||
const int aPropIndex = aList.size() != 2 ? 0 : aList.back().IntegerValue();
|
||||
|
||||
theSelProperty = theDataSource->NodalQuantities().Value(aPropIndex);
|
||||
const Standard_Boolean isGrayscale = isGrayscaleProperty(theSelProperty->Name());
|
||||
const Standard_Integer aMeshEdgesLimit = 100000;
|
||||
if (!isGrayscale
|
||||
&& (aMeshEdgesLimit < 0 || theDataSource->NbNodes() <= aMeshEdgesLimit))
|
||||
{
|
||||
aDrawer->SetBoolean(MeshVS_DA_ShowEdges, Standard_True);
|
||||
}
|
||||
aDrawer->SetBoolean(MeshVS_DA_ColorReflection, Standard_True);
|
||||
|
||||
Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_NodalColorDataPrs);
|
||||
aBuilder->SetProperty(theSelProperty, Standard_False);
|
||||
aBuilder->SetGrayscale(isGrayscale);
|
||||
|
||||
aMesh->AddBuilder(aBuilder, Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_NodalColorDataPrs);
|
||||
}
|
||||
//else if (theSelEntry.startsWith("ply_group_elemprops\n"))
|
||||
else if (theSelEntry.Search("ply_group_elemprops\n") != -1)
|
||||
{
|
||||
//myPrsCaps |= DisplayCaps_Texture;
|
||||
std::vector<TCollection_AsciiString> aList = Split(theEntry, "\n");
|
||||
const int aPropIndex = aList.size() != 2 ? 0 : aList.back().IntegerValue();
|
||||
|
||||
aDrawer->SetBoolean(MeshVS_DA_ColorReflection, Standard_True);
|
||||
|
||||
theSelProperty = theDataSource->ElementalQuantities().Value(aPropIndex);
|
||||
|
||||
Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_ElementalColorDataPrs);
|
||||
aBuilder->SetProperty(theSelProperty, Standard_True);
|
||||
aBuilder->SetGrayscale(isGrayscaleProperty(theSelProperty->Name()));
|
||||
|
||||
aMesh->AddBuilder(aBuilder, Standard_True);
|
||||
aMesh->SetDisplayMode(MeshVS_DMF_ElementalColorDataPrs);
|
||||
}
|
||||
|
||||
return aMesh;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// function : VDisplayObj
|
||||
// purpose :
|
||||
// =============================================================================
|
||||
static int VDisplayObj (Draw_Interpretor& theDi,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
if (theArgNb < 3)
|
||||
{
|
||||
theDi << theArgVec[0] << "Error: wrong number of arguments.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const TCollection_AsciiString aName (theArgVec[1]);
|
||||
const TCollection_AsciiString aPath (theArgVec[2]);
|
||||
|
||||
if (GetMapOfAIS().IsBound2(aName))
|
||||
{
|
||||
theDi << aName << "already exist.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Handle(ObjDataSource) aLoader = new ObjDataSource();
|
||||
|
||||
Standard_Boolean aResult = aLoader->Read (aPath, NULL, -1, -1);
|
||||
|
||||
if (!aResult)
|
||||
{
|
||||
theDi << "Error: can't read a file: '" << aPath.ToCString() << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*const NCollection_Vector<MeshGroup>& aGroups = aLoader->Groups();
|
||||
for (auto anIter = aGroups.cbegin(); anIter != aGroups.cend(); ++anIter)
|
||||
{
|
||||
const Quantity_Color& aDiffuseColor = anIter->Material.Aspect.DiffuseColor();
|
||||
const Graphic3d_BSDF& aBSDF = anIter->Material.Aspect.BSDF();
|
||||
|
||||
std::cout << anIter->Material.Texture << std::endl;
|
||||
std::cout << aDiffuseColor.Red() << ", " << aDiffuseColor.Green() << ", " << aDiffuseColor.Green() << std::endl;
|
||||
std::cout << aBSDF.Kd.x() << ", " << aBSDF.Kd.y() << ", " << aBSDF.Kd.z() << std::endl << std::endl;
|
||||
}*/
|
||||
|
||||
Handle(MeshScalarProperty) aProperty;
|
||||
TCollection_AsciiString aSelEntry;
|
||||
Handle(MeshVS_Mesh) aMesh = createMeshPresentation(aLoader, "", aSelEntry, aProperty);
|
||||
|
||||
ViewerTest::Display(aName, aMesh, Standard_False);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <ObjDataWriter.h>
|
||||
#include <AIS_ListOfInteractive.hxx>
|
||||
// =============================================================================
|
||||
// function : VSaveObj
|
||||
// purpose :
|
||||
// =============================================================================
|
||||
static int VSaveObj (Draw_Interpretor& theDi,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
if (theArgNb < 3)
|
||||
{
|
||||
theDi << theArgVec[0] << "Error: wrong number of arguments.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const TCollection_AsciiString aPath (theArgVec[1]);
|
||||
AIS_ListOfInteractive aList;
|
||||
Handle(ObjDataWriter) aWriter = new ObjDataWriter();
|
||||
|
||||
for (Standard_Integer anIter = 2; anIter < theArgNb; ++anIter)
|
||||
{
|
||||
TCollection_AsciiString aName (theArgVec[anIter]);
|
||||
|
||||
if (!GetMapOfAIS().IsBound2(aName))
|
||||
{
|
||||
theDi << aName << "is not exist.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(aName));
|
||||
if (anObject.IsNull())
|
||||
{
|
||||
theDi << aName << "is not an interactive object.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Handle(MeshVS_Mesh) aMesh = Handle(MeshVS_Mesh)::DownCast(anObject);
|
||||
if (!aMesh.IsNull())
|
||||
{
|
||||
aWriter->Write (aMesh->GetDataSource(), aPath, NULL);
|
||||
}*/
|
||||
|
||||
aList.Append(anObject);
|
||||
}
|
||||
aWriter->Write (aList, aPath, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : ViewerTest::Commands
|
||||
//purpose : Add all the viewer command in the Draw_Interpretor
|
||||
@@ -5556,6 +5725,14 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
|
||||
"\n\t\t: -redisplay recomputes presentation of objects.",
|
||||
__FILE__, VDisplay2, group);
|
||||
|
||||
theCommands.Add("vdisplayobj",
|
||||
"vdisplayobj name path",
|
||||
__FILE__, VDisplayObj, group);
|
||||
|
||||
theCommands.Add("vsaveobj",
|
||||
"vsaveobj file names",
|
||||
__FILE__, VSaveObj, group);
|
||||
|
||||
theCommands.Add ("vupdate",
|
||||
"vupdate name1 [name2] ... [name n]"
|
||||
"\n\t\t: Updates named objects in interactive context",
|
||||
@@ -5757,10 +5934,6 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
|
||||
"\n\t\t: Tests the animation of an object along a predefined trajectory.",
|
||||
__FILE__,VPerf,group);
|
||||
|
||||
theCommands.Add("vanimation",
|
||||
"vanimation CrankArmFile CylinderHeadFile PropellerFile EngineBlockFile",
|
||||
__FILE__,VAnimation,group);
|
||||
|
||||
theCommands.Add("vsetshading",
|
||||
"vsetshading : vsetshading name Quality(default=0.0008) "
|
||||
"\n\t\t: Sets deflection coefficient that defines the quality of the shape representation in the shading mode.",
|
||||
|
@@ -15,13 +15,24 @@
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
|
||||
#include <windows.h>
|
||||
#include <Aspect_Window.hxx>
|
||||
#include <OpenGl_AVIWriter.hxx>
|
||||
#include <V3d_View.hxx>
|
||||
#endif
|
||||
|
||||
#include <ViewerTest.hxx>
|
||||
|
||||
#include <Aspect_Window.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Message_ProgressSentry.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <Image_PixMap.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <V3d_View.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
static Standard_Integer avi_record(Draw_Interpretor& /*di*/,
|
||||
Standard_Integer argc, const char** argv)
|
||||
@@ -84,14 +95,889 @@ static Standard_Integer avi_record(Draw_Interpretor& /*di*/,
|
||||
return aResult;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma comment(lib, "avutil.lib")
|
||||
#pragma comment(lib, "avcodec.lib")
|
||||
#pragma comment(lib, "avformat.lib")
|
||||
#pragma comment(lib, "swscale.lib")
|
||||
|
||||
// suppress some common warnings in FFmpeg headers
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default : 4244)
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Video recording tool.
|
||||
class ViewerTest_VideoRecorder : public Standard_Transient
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
ViewerTest_VideoRecorder()
|
||||
: myAVContext (NULL),
|
||||
myVideoStream (NULL),
|
||||
myVideoCodec (NULL),
|
||||
myFrame (NULL),
|
||||
myScaleCtx (NULL),
|
||||
myPixFmtOut (AV_PIX_FMT_YUV420P),
|
||||
myPixFmtSrc (AV_PIX_FMT_RGBA), // AV_PIX_FMT_BGR0
|
||||
myFrameCount (0)
|
||||
{
|
||||
myFrameRate.num = 1;
|
||||
myFrameRate.den = 30;
|
||||
|
||||
// initialize libavcodec, and register all codecs and formats, should be done once
|
||||
av_register_all();
|
||||
}
|
||||
|
||||
//! Destructor.
|
||||
~ViewerTest_VideoRecorder()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//! Setup playback FPS. Should be set before Open().
|
||||
void SetFramerate (const Standard_Integer theNumerator,
|
||||
const Standard_Integer theDenominator)
|
||||
{
|
||||
myFrameRate.num = theNumerator;
|
||||
myFrameRate.den = theDenominator;
|
||||
}
|
||||
|
||||
//! Setup playback FPS. Should be set before Open().
|
||||
//! For fixed-fps content, timebase should be 1/framerate and timestamp increments should be identical to 1.
|
||||
void SetFramerate (const Standard_Integer theValue)
|
||||
{
|
||||
myFrameRate.num = int(theValue);
|
||||
myFrameRate.den = 1;
|
||||
}
|
||||
|
||||
//! Close the stream - stop recorder.
|
||||
void Close()
|
||||
{
|
||||
if (myScaleCtx != NULL)
|
||||
{
|
||||
sws_freeContext (myScaleCtx);
|
||||
}
|
||||
|
||||
if (myAVContext == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the trailer, if any. The trailer must be written before you close the CodecContexts open when you wrote the header;
|
||||
// otherwise av_write_trailer() may try to use memory that was freed on av_codec_close().
|
||||
av_write_trailer (myAVContext);
|
||||
|
||||
// close each codec
|
||||
if (myVideoStream != NULL)
|
||||
{
|
||||
avcodec_close (myVideoStream->codec);
|
||||
myVideoStream = NULL;
|
||||
}
|
||||
if (myFrame != NULL)
|
||||
{
|
||||
av_free (myPicDst.data[0]);
|
||||
av_frame_free (&myFrame);
|
||||
myFrame = NULL;
|
||||
}
|
||||
|
||||
if (!(myAVContext->oformat->flags & AVFMT_NOFILE))
|
||||
{
|
||||
// close the output file
|
||||
avio_close (myAVContext->pb);
|
||||
}
|
||||
|
||||
// free the stream
|
||||
avformat_free_context (myAVContext);
|
||||
myAVContext = NULL;
|
||||
}
|
||||
|
||||
//! Open output stream - start recorder.
|
||||
Standard_Boolean Open (const char* theFileName,
|
||||
const Standard_Integer theWidth,
|
||||
const Standard_Integer theHeight)
|
||||
{
|
||||
Close();
|
||||
myFrameCount = 0;
|
||||
if (theWidth <= 0
|
||||
|| theHeight <= 0)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// allocate the output media context
|
||||
avformat_alloc_output_context2 (&myAVContext, NULL, NULL, theFileName);
|
||||
if (myAVContext == NULL)
|
||||
{
|
||||
::Message::DefaultMessenger()->Send ("ViewerTest_VideoRecorder, could not deduce output format from file extension - using MPEG.", Message_Warning);
|
||||
avformat_alloc_output_context2 (&myAVContext, NULL, "mpeg", theFileName);
|
||||
}
|
||||
if (myAVContext == NULL)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// add the audio stream using the default format codecs and initialize the codecs
|
||||
if (!addVideoStream (myAVContext->oformat->video_codec, theWidth, theHeight))
|
||||
{
|
||||
Close();
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// open video codec and allocate the necessary encode buffers
|
||||
if (!openVideoCodec())
|
||||
{
|
||||
Close();
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
av_dump_format (myAVContext, 0, theFileName, 1); /// debug
|
||||
|
||||
// open the output file, if needed
|
||||
if ((myAVContext->oformat->flags & AVFMT_NOFILE) == 0)
|
||||
{
|
||||
const int aResAv = avio_open (&myAVContext->pb, theFileName, AVIO_FLAG_WRITE);
|
||||
if (aResAv < 0)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: could not open '") + theFileName + "', " + formatAvError (aResAv);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
Close();
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
|
||||
// write the stream header, if any
|
||||
const int aResAv = avformat_write_header (myAVContext, NULL);
|
||||
if (aResAv < 0)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not open output file '") + theFileName + "', " + formatAvError (aResAv);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
Close();
|
||||
return Standard_False;
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//! Access RGBA frame, should NOT be re-initialized outside.
|
||||
Image_PixMap& ChangeFrame()
|
||||
{
|
||||
return myImgSrcRgba;
|
||||
}
|
||||
|
||||
//! Push new frame, should be called after Open().
|
||||
Standard_Boolean PushFrame()
|
||||
{
|
||||
return writeVideoFrame (Standard_False);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Wrapper for av_strerror().
|
||||
TCollection_AsciiString formatAvError (const int theError) const
|
||||
{
|
||||
char anErrBuf[AV_ERROR_MAX_STRING_SIZE] = {};
|
||||
av_strerror (theError, anErrBuf, AV_ERROR_MAX_STRING_SIZE);
|
||||
return anErrBuf;
|
||||
}
|
||||
|
||||
//! Append video stream.
|
||||
Standard_Boolean addVideoStream (const AVCodecID theCodecId,
|
||||
const Standard_Integer theWidth,
|
||||
const Standard_Integer theHeight)
|
||||
{
|
||||
// find the encoder
|
||||
myVideoCodec = avcodec_find_encoder (theCodecId);
|
||||
if (myVideoCodec == NULL)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not find encoder for ") + avcodec_get_name (theCodecId);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
myVideoStream = avformat_new_stream (myAVContext, myVideoCodec);
|
||||
if (myVideoStream == NULL)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate stream!");
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
myVideoStream->id = myAVContext->nb_streams - 1;
|
||||
|
||||
AVCodecContext* aCodecCtx = myVideoStream->codec;
|
||||
aCodecCtx->codec_id = theCodecId;
|
||||
// resolution must be a multiple of two
|
||||
aCodecCtx->width = theWidth;
|
||||
aCodecCtx->height = theHeight;
|
||||
// Timebase is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
|
||||
// For fixed-fps content, timebase should be 1/framerate and timestamp increments should be identical to 1.
|
||||
aCodecCtx->time_base.den = myFrameRate.num;
|
||||
aCodecCtx->time_base.num = myFrameRate.den;
|
||||
aCodecCtx->gop_size = 12; // emit one intra frame every twelve frames at most
|
||||
aCodecCtx->pix_fmt = myPixFmtOut;
|
||||
|
||||
// some formats want stream headers to be separate
|
||||
if (myAVContext->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
{
|
||||
aCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//! Open video codec.
|
||||
Standard_Boolean openVideoCodec()
|
||||
{
|
||||
// open the codec
|
||||
AVCodecContext* aCodecCtx = myVideoStream->codec;
|
||||
|
||||
AVDictionary* anOptions = NULL;
|
||||
//av_dict_set (&anOptions, "threads", "auto", 0);
|
||||
switch (aCodecCtx->codec_id)
|
||||
{
|
||||
case AV_CODEC_ID_MPEG2VIDEO:
|
||||
{
|
||||
// just for testing, we also add B frames
|
||||
aCodecCtx->max_b_frames = 2;
|
||||
aCodecCtx->bit_rate = 6000000;
|
||||
break;
|
||||
}
|
||||
case AV_CODEC_ID_H264:
|
||||
{
|
||||
// use CRF (Constant Rate Factor) as best single-pass compressing method
|
||||
av_dict_set (&anOptions, "crf", "20", 0); // quality 18-28, 23 is default (normal), 18 is almost lossless
|
||||
av_dict_set (&anOptions, "preset", "slow", 0); // good compression (see also "veryslow", "ultrafast")
|
||||
|
||||
// live-capturing
|
||||
//av_dict_set (&anOptions, "qp", "0", 0); // instead of crf
|
||||
//av_dict_set (&anOptions, "preset", "ultrafast", 0);
|
||||
|
||||
// compatibility with devices
|
||||
//av_dict_set (&anOptions, "profile", "baseline", 0);
|
||||
//av_dict_set (&anOptions, "level", "3.0", 0);
|
||||
break;
|
||||
}
|
||||
/*case AV_CODEC_ID_VP8:
|
||||
case AV_CODEC_ID_VP9:
|
||||
{
|
||||
av_dict_set (&anOptions, "crf", "20", 0); // quality 4<>63, 10 is normal
|
||||
break;
|
||||
}*/
|
||||
}
|
||||
|
||||
int aResAv = avcodec_open2 (aCodecCtx, myVideoCodec, &anOptions);
|
||||
if (anOptions != NULL)
|
||||
{
|
||||
av_dict_free (&anOptions);
|
||||
}
|
||||
if (aResAv < 0)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not open video codec, ") + formatAvError (aResAv);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// allocate and init a re-usable frame
|
||||
myFrame = av_frame_alloc();
|
||||
if (myFrame == NULL)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate video frame!");
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// allocate the encoded raw picture
|
||||
aResAv = avpicture_alloc (&myPicDst, aCodecCtx->pix_fmt, aCodecCtx->width, aCodecCtx->height);
|
||||
if (aResAv < 0)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate picture ")
|
||||
+ aCodecCtx->width+ "x" + aCodecCtx->height + ", " + formatAvError (aResAv);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
// copy data and linesize picture pointers to frame
|
||||
myFrame->format = aCodecCtx->pix_fmt;
|
||||
myFrame->width = aCodecCtx->width;
|
||||
myFrame->height = aCodecCtx->height;
|
||||
*((AVPicture* )myFrame) = myPicDst;
|
||||
|
||||
const Standard_Size aStride = aCodecCtx->width + 16 - (aCodecCtx->width % 16);
|
||||
if (!myImgSrcRgba.InitZero (Image_PixMap::ImgRGBA, aCodecCtx->width, aCodecCtx->height, aStride))
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate RGBA32 picture ")
|
||||
+ aCodecCtx->width+ "x" + aCodecCtx->height;
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
myImgSrcRgba.SetTopDown(true);
|
||||
|
||||
myScaleCtx = sws_getContext (aCodecCtx->width, aCodecCtx->height, myPixFmtSrc,
|
||||
aCodecCtx->width, aCodecCtx->height, aCodecCtx->pix_fmt,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
if (myScaleCtx == NULL)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not initialize the conversion context!");
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//! Write new video frame.
|
||||
Standard_Boolean writeVideoFrame (const Standard_Boolean theToFlush)
|
||||
{
|
||||
int aResAv = 0;
|
||||
AVCodecContext* aCodecCtx = myVideoStream->codec;
|
||||
if (!theToFlush)
|
||||
{
|
||||
uint8_t* aSrcData[4] = { (uint8_t*)myImgSrcRgba.ChangeData(), NULL, NULL, NULL };
|
||||
int aSrcLinesize[4] = { (int )myImgSrcRgba.SizeRowBytes(), 0, 0, 0 };
|
||||
sws_scale (myScaleCtx,
|
||||
aSrcData, aSrcLinesize,
|
||||
0, aCodecCtx->height,
|
||||
myPicDst.data, myPicDst.linesize);
|
||||
}
|
||||
|
||||
AVPacket aPacket = { 0 };
|
||||
av_init_packet (&aPacket);
|
||||
if ((myAVContext->oformat->flags & AVFMT_RAWPICTURE) != 0
|
||||
&& !theToFlush)
|
||||
{
|
||||
// raw video case - directly store the picture in the packet
|
||||
aPacket.flags |= AV_PKT_FLAG_KEY;
|
||||
aPacket.stream_index = myVideoStream->index;
|
||||
aPacket.data = myPicDst.data[0];
|
||||
aPacket.size = sizeof(AVPicture);
|
||||
|
||||
aResAv = av_interleaved_write_frame (myAVContext, &aPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode the image
|
||||
myFrame->pts = myFrameCount;
|
||||
int isGotPacket = 0;
|
||||
aResAv = avcodec_encode_video2 (aCodecCtx, &aPacket, theToFlush ? NULL : myFrame, &isGotPacket);
|
||||
if (aResAv < 0)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not encode video frame, ") + formatAvError (aResAv);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// if size is zero, it means the image was buffered
|
||||
if (isGotPacket)
|
||||
{
|
||||
const AVRational& aTimeBase = aCodecCtx->time_base;
|
||||
|
||||
// rescale output packet timestamp values from codec to stream timebase
|
||||
aPacket.pts = av_rescale_q_rnd (aPacket.pts, aTimeBase, myVideoStream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
|
||||
aPacket.dts = av_rescale_q_rnd (aPacket.dts, aTimeBase, myVideoStream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
|
||||
aPacket.duration = av_rescale_q (aPacket.duration, aTimeBase, myVideoStream->time_base);
|
||||
aPacket.stream_index = myVideoStream->index;
|
||||
|
||||
// write the compressed frame to the media file
|
||||
aResAv = av_interleaved_write_frame (myAVContext, &aPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
aResAv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (aResAv < 0)
|
||||
{
|
||||
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not write video frame, ") + formatAvError (aResAv);
|
||||
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
|
||||
return Standard_False;
|
||||
}
|
||||
++myFrameCount;
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
AVFormatContext* myAVContext;
|
||||
AVStream* myVideoStream;
|
||||
AVCodec* myVideoCodec;
|
||||
AVFrame* myFrame;
|
||||
AVPicture myPicDst;
|
||||
SwsContext* myScaleCtx;
|
||||
AVRational myFrameRate;
|
||||
AVPixelFormat myPixFmtOut;
|
||||
|
||||
Image_PixMap myImgSrcRgba;
|
||||
AVPixelFormat myPixFmtSrc;
|
||||
|
||||
int64_t myFrameCount;
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(ViewerTest_VideoRecorder, Standard_Transient) // Type definition
|
||||
|
||||
};
|
||||
|
||||
//DEFINE_STANDARD_HANDLE(ViewerTest_VideoRecorder, Standard_Transient)
|
||||
//IMPLEMENT_STANDARD_HANDLE (ViewerTest_VideoRecorder, Standard_Transient)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_VideoRecorder, Standard_Transient)
|
||||
//DEFINE_STANDARD_HANDLE(ViewerTest_Animation, Standard_Transient)
|
||||
|
||||
//! Structure defining animation sequence
|
||||
class ViewerTest_Animation : public Standard_Transient
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Connected animation slice
|
||||
struct Slice
|
||||
{
|
||||
|
||||
Standard_Real StartTime; //!< presentation timestamp within parent animation slice
|
||||
Standard_Real Duration; //!< animation duration
|
||||
Handle(ViewerTest_Animation) Animation; //!< connected animation to be executed
|
||||
|
||||
Slice() : StartTime (0.0), Duration (0.0) {}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
TCollection_AsciiString OnStart; //!< procedure to be evaluated at the beggining of this animation slice
|
||||
TCollection_AsciiString OnEnd; //!< procedure to be evaluated at the end of this animation slice
|
||||
TCollection_AsciiString OnRedraw; //!< procedure to be evaluated at every frame during this animation slice
|
||||
NCollection_Sequence<Slice> Slices; //!< sequence of child animation slices
|
||||
|
||||
public:
|
||||
|
||||
//! Empty constructor
|
||||
ViewerTest_Animation() {}
|
||||
|
||||
//! Reset the animation definition
|
||||
void Reset()
|
||||
{
|
||||
OnStart.Clear();
|
||||
OnEnd.Clear();
|
||||
OnRedraw.Clear();
|
||||
Slices.Clear();
|
||||
}
|
||||
|
||||
//! Estimated duration
|
||||
Standard_Real Duration() const
|
||||
{
|
||||
Standard_Real aDuration = -1.0;
|
||||
for (NCollection_Sequence<Slice>::Iterator aSliceIter (Slices);
|
||||
aSliceIter.More(); aSliceIter.Next())
|
||||
{
|
||||
Standard_Real aSliceDuration = aSliceIter.Value().Duration >= 0.0
|
||||
? aSliceIter.Value().Duration
|
||||
: aSliceIter.Value().Animation->Duration();
|
||||
aDuration = Max (aDuration, aSliceIter.Value().StartTime + aSliceDuration);
|
||||
}
|
||||
return aDuration;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(ViewerTest_Animation,Standard_Transient) // Type definition
|
||||
|
||||
};
|
||||
|
||||
//IMPLEMENT_STANDARD_HANDLE (ViewerTest_Animation, Standard_Transient)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_Animation, Standard_Transient)
|
||||
|
||||
static NCollection_DataMap<TCollection_AsciiString, Handle(ViewerTest_Animation)> ViewerTest_TheAnimationsMap;
|
||||
|
||||
//! Evaluate animation sequence
|
||||
static void VEvalAnimation (Draw_Interpretor& theDI,
|
||||
const ViewerTest_Animation& theAnim,
|
||||
const Standard_Real theStartPts,
|
||||
const Standard_Real theEndPts,
|
||||
const Standard_Real thePrevPts,
|
||||
const Standard_Real thePts)
|
||||
{
|
||||
const Standard_Real aLocPts = thePts - theStartPts;
|
||||
if ( thePts >= theStartPts
|
||||
&& thePrevPts < theStartPts
|
||||
&& !theAnim.OnStart.IsEmpty())
|
||||
{
|
||||
const TCollection_AsciiString aCmd = theAnim.OnStart + " " + thePts + " " + aLocPts + " onStart";
|
||||
theDI.Eval (aCmd.ToCString());
|
||||
}
|
||||
|
||||
for (NCollection_Sequence<ViewerTest_Animation::Slice>::Iterator aSliceIter (theAnim.Slices);
|
||||
aSliceIter.More(); aSliceIter.Next())
|
||||
{
|
||||
VEvalAnimation (theDI,
|
||||
*aSliceIter.Value().Animation,
|
||||
aSliceIter.Value().StartTime,
|
||||
aSliceIter.Value().StartTime + aSliceIter.Value().Duration,
|
||||
thePrevPts,
|
||||
thePts);
|
||||
}
|
||||
|
||||
if (!theAnim.OnRedraw.IsEmpty()
|
||||
&& thePts >= theStartPts
|
||||
&& thePts < theEndPts)
|
||||
{
|
||||
const TCollection_AsciiString aCmd = theAnim.OnRedraw + " " + thePts + " " + aLocPts + " onRedraw";
|
||||
theDI.Eval (aCmd.ToCString());
|
||||
}
|
||||
|
||||
if ( thePts >= theEndPts
|
||||
&& thePrevPts < theEndPts
|
||||
&& !theAnim.OnEnd.IsEmpty())
|
||||
{
|
||||
const TCollection_AsciiString aCmd = theAnim.OnEnd + " " + thePts + " " + aLocPts + " onEnd";
|
||||
theDI.Eval (aCmd.ToCString());
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : VAnimation
|
||||
//purpose :
|
||||
//==============================================================================
|
||||
static Standard_Integer VAnimation (Draw_Interpretor& theDI,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
|
||||
if (theArgNb < 2)
|
||||
{
|
||||
for (NCollection_DataMap<TCollection_AsciiString, Handle(ViewerTest_Animation)>::Iterator anAnimIter (ViewerTest_TheAnimationsMap);
|
||||
anAnimIter.More(); anAnimIter.Next())
|
||||
{
|
||||
theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Standard_Boolean toPlay = Standard_False;
|
||||
Standard_Boolean isInteractive = Standard_False;
|
||||
Standard_Real aPlayFrom = 0.0;
|
||||
Standard_Real aPlayDuration = -1.0;
|
||||
Standard_Integer aPlayFpsNum = 0;
|
||||
Standard_Integer aPlayFpsDen = 1;
|
||||
Standard_CString aRecordFile = NULL;
|
||||
Standard_Integer aRecWidth = 0;
|
||||
Standard_Integer aRecHeight = 0;
|
||||
TCollection_AsciiString aName;
|
||||
Handle(ViewerTest_Animation) anAnim;
|
||||
Standard_Integer anArgIter = 1;
|
||||
for (; anArgIter < theArgNb; ++anArgIter)
|
||||
{
|
||||
Standard_CString anArg = theArgVec[anArgIter];
|
||||
TCollection_AsciiString anArgCase (anArg);
|
||||
anArgCase.LowerCase();
|
||||
if (anArgCase == "-onstart")
|
||||
{
|
||||
if (++anArgIter >= theArgNb
|
||||
|| anAnim.IsNull())
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
anAnim->OnStart = theArgVec[anArgIter];
|
||||
}
|
||||
else if (anArgCase == "-onend")
|
||||
{
|
||||
if (++anArgIter >= theArgNb
|
||||
|| anAnim.IsNull())
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
anAnim->OnEnd = theArgVec[anArgIter];
|
||||
}
|
||||
else if (anArgCase == "-onredraw"
|
||||
|| anArgCase == "-ondraw")
|
||||
{
|
||||
if (++anArgIter >= theArgNb
|
||||
|| anAnim.IsNull())
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
anAnim->OnRedraw = theArgVec[anArgIter];
|
||||
}
|
||||
else if (anArgCase == "-reset")
|
||||
{
|
||||
if (anAnim.IsNull())
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
anAnim->Reset();
|
||||
}
|
||||
else if (anArgCase == "-delete")
|
||||
{
|
||||
if (++anArgIter < theArgNb
|
||||
|| anAnim.IsNull())
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
ViewerTest_TheAnimationsMap.UnBind (aName);
|
||||
}
|
||||
else if (anArgCase == "-addslice"
|
||||
|| anArgCase == "-slice")
|
||||
{
|
||||
if (anArgIter + 3 >= theArgNb
|
||||
|| anAnim.IsNull())
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
ViewerTest_Animation::Slice aSlice;
|
||||
aSlice.StartTime = Draw::Atof (theArgVec[++anArgIter]);
|
||||
aSlice.Duration = Draw::Atof (theArgVec[++anArgIter]);
|
||||
if (aSlice.StartTime < 0.0)
|
||||
{
|
||||
std::cout << "Error: PTS should not be negative (specified " << aSlice.StartTime << ")\n";
|
||||
return 1;
|
||||
}
|
||||
TCollection_AsciiString anOtherName (theArgVec[++anArgIter]);
|
||||
if (!ViewerTest_TheAnimationsMap.Find (anOtherName, aSlice.Animation))
|
||||
{
|
||||
std::cout << "Error: animation with name '" << anOtherName << "' is not registered!\n";
|
||||
return 1;
|
||||
}
|
||||
Standard_Integer anIndex = 1;
|
||||
for (NCollection_Sequence<ViewerTest_Animation::Slice>::Iterator aSliceIter (anAnim->Slices);
|
||||
aSliceIter.More(); aSliceIter.Next(), ++anIndex)
|
||||
{
|
||||
if (aSlice.StartTime < aSliceIter.Value().StartTime)
|
||||
{
|
||||
anAnim->Slices.InsertBefore (anIndex, aSlice);
|
||||
anIndex = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (anIndex != -1)
|
||||
{
|
||||
anAnim->Slices.Append (aSlice);
|
||||
}
|
||||
}
|
||||
else if (anArgCase == "-play")
|
||||
{
|
||||
toPlay = Standard_True;
|
||||
}
|
||||
else if (anArgCase == "-playfrom")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
aPlayFrom = Draw::Atof (theArgVec[anArgIter]);
|
||||
}
|
||||
else if (anArgCase == "-playduration"
|
||||
|| anArgCase == "-playdur")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
|
||||
}
|
||||
else if (anArgCase == "-playfps"
|
||||
|| anArgCase == "-fps")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
TCollection_AsciiString aFpsStr (theArgVec[anArgIter]);
|
||||
Standard_Integer aSplitIndex = aFpsStr.FirstLocationInSet ("/", 1, aFpsStr.Length());
|
||||
if (aSplitIndex == 0)
|
||||
{
|
||||
aPlayFpsNum = aFpsStr.IntegerValue();
|
||||
aPlayFpsDen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const TCollection_AsciiString aDenStr = aFpsStr.Split (aSplitIndex);
|
||||
aFpsStr.Split (aFpsStr.Length() - 1);
|
||||
const TCollection_AsciiString aNumStr = aFpsStr;
|
||||
aPlayFpsNum = aNumStr.IntegerValue();
|
||||
aPlayFpsDen = aDenStr.IntegerValue();
|
||||
if (aPlayFpsDen < 1)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (anArgCase == "-inter"
|
||||
|| anArgCase == "-interactive")
|
||||
{
|
||||
isInteractive = Standard_True;
|
||||
}
|
||||
else if (anArgCase == "-rec"
|
||||
|| anArgCase == "-record")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
aRecordFile = theArgVec[anArgIter];
|
||||
}
|
||||
else if (anArgCase == "-recwidth"
|
||||
|| anArgCase == "-recordwidth")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
aRecWidth = Draw::Atoi (theArgVec[anArgIter]);
|
||||
}
|
||||
else if (anArgCase == "-recheight"
|
||||
|| anArgCase == "-recordheight")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
aRecHeight = Draw::Atoi (theArgVec[anArgIter]);
|
||||
}
|
||||
else if (aName.IsEmpty())
|
||||
{
|
||||
aName = anArg;
|
||||
if (!ViewerTest_TheAnimationsMap.Find (aName, anAnim))
|
||||
{
|
||||
anAnim = new ViewerTest_Animation();
|
||||
ViewerTest_TheAnimationsMap.Bind (aName, anAnim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error: wrong syntax at '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!toPlay)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// play animation
|
||||
if (aPlayDuration < 0.0)
|
||||
{
|
||||
aPlayDuration = anAnim->Duration();
|
||||
}
|
||||
Standard_Real aPtsTo = aPlayFrom + aPlayDuration;
|
||||
OSD_Timer aTimer;
|
||||
aTimer.Start();
|
||||
Standard_Real aPrevPts = aPlayFrom - Precision::Confusion();
|
||||
if (aPlayFpsNum > 0)
|
||||
{
|
||||
const Handle(V3d_View)& aView = ViewerTest::CurrentView();
|
||||
Handle(ViewerTest_VideoRecorder) aRecorder;
|
||||
if (aRecordFile != NULL)
|
||||
{
|
||||
if (aView.IsNull())
|
||||
{
|
||||
std::cout << "Error: no active view!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Standard_Integer aWinWidth = 0, aWinHeight = 0;
|
||||
aView->Window()->Size (aWinWidth, aWinHeight);
|
||||
if (aRecWidth <= 0)
|
||||
{
|
||||
aRecWidth = aWinWidth;
|
||||
}
|
||||
if (aRecHeight <= 0)
|
||||
{
|
||||
aRecHeight = aWinHeight;
|
||||
}
|
||||
|
||||
aRecorder = new ViewerTest_VideoRecorder();
|
||||
aRecorder->SetFramerate (aPlayFpsNum, aPlayFpsDen);
|
||||
if (!aRecorder->Open (aRecordFile, aRecWidth, aRecHeight))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// fixed FPS, bad formula - to be corrected
|
||||
const Standard_Real aFrameDur = Standard_Real(aPlayFpsDen) / Standard_Real(aPlayFpsNum);
|
||||
for (Standard_Real aPts = aPlayFrom; aPts <= aPtsTo; aPts += aFrameDur)
|
||||
{
|
||||
VEvalAnimation (theDI, *anAnim,
|
||||
aPlayFrom, aPtsTo,
|
||||
aPrevPts, aPts);
|
||||
aPrevPts = aPts;
|
||||
if (!aRecorder.IsNull())
|
||||
{
|
||||
if (!aView->ToPixMap (aRecorder->ChangeFrame(),
|
||||
aRecorder->ChangeFrame().SizeX(), aRecorder->ChangeFrame().SizeY(),
|
||||
Graphic3d_BT_RGBA, Standard_True, V3d_SDO_MONO))
|
||||
{
|
||||
std::cout << "Error: view dump is failed!\n";
|
||||
return 0;
|
||||
}
|
||||
if (!aRecorder->PushFrame())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (isInteractive)
|
||||
{
|
||||
// handle user events
|
||||
theDI.Eval ("after 1 set waiter 1");
|
||||
theDI.Eval ("vwait waiter");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// live playback
|
||||
for (Standard_Real aPts = aPlayFrom; aPts <= aPtsTo; aPts = aTimer.ElapsedTime())
|
||||
{
|
||||
VEvalAnimation (theDI, *anAnim,
|
||||
aPlayFrom, aPtsTo,
|
||||
aPrevPts, aPts);
|
||||
aPrevPts = aPts;
|
||||
if (isInteractive)
|
||||
{
|
||||
// handle user events
|
||||
theDI.Eval ("after 1 set waiter 1");
|
||||
theDI.Eval ("vwait waiter");
|
||||
}
|
||||
}
|
||||
}
|
||||
aTimer.Show();
|
||||
//theDI << "Duration: " << aTimer.ElapsedTime() << " sec.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AviCommands
|
||||
//purpose :
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void ViewerTest::AviCommands(Draw_Interpretor& theCommands)
|
||||
{
|
||||
const char* group = "ViewerTest AVI commands";
|
||||
const char* aGroup = "ViewerTest AVI commands";
|
||||
|
||||
theCommands.Add("vrecord", "vrecord [option]\n"
|
||||
"where [option] can be:\n"
|
||||
@@ -102,5 +988,51 @@ void ViewerTest::AviCommands(Draw_Interpretor& theCommands)
|
||||
"\tstatus : log error message,\n"
|
||||
"\tsave : close the AVI file\n",
|
||||
__FILE__,
|
||||
&avi_record, group); //Draft_Modification
|
||||
&avi_record, aGroup); //Draft_Modification
|
||||
|
||||
theCommands.Add("vanimation", "Alias for vanimation",
|
||||
__FILE__, VAnimation, aGroup);
|
||||
|
||||
theCommands.Add("vanim",
|
||||
"List existing animations:"
|
||||
"\n\t\t: vanim"
|
||||
"\n\t\t: Animation playback:"
|
||||
"\n\t\t: vanim -play AnimName [-interactive] [-fps FPS=0/1]"
|
||||
"\n\t\t: [-playFrom Sec=0] [-playDuration Sec=-1.0]"
|
||||
"\n\t\t: [-record VideoFileName]"
|
||||
"\n\t\t: [-recordWidth Width] [-recordHeight Height]"
|
||||
"\n\t\t: where"
|
||||
"\n\t\t: -interactive handle user events on idle"
|
||||
"\n\t\t: -playFrom animation start PTS"
|
||||
"\n\t\t: -playDuration animation duration"
|
||||
"\n\t\t: -playFps constant framerate for recording (e.g. 30/1),"
|
||||
"\n\t\t: disables live time"
|
||||
"\n\t\t: -record record to the file"
|
||||
"\n\t\t: -recordWidth width of recorded video"
|
||||
"\n\t\t: (window width if not set)"
|
||||
"\n\t\t: -recordHeight height of recorded video"
|
||||
"\n\t\t: (window height if not set)"
|
||||
"\n\t\t: Animation definition:"
|
||||
"\n\t\t: vanim AnimName"
|
||||
"\n\t\t: -delete"
|
||||
"\n\t\t: -onStart StartProcName"
|
||||
"\n\t\t: -onEnd EndProcName"
|
||||
"\n\t\t: -onRedraw AnimProcName"
|
||||
"\n\t\t: -addSlice FromPts Duration OtherAnimName"
|
||||
"\n\t\t: -reset"
|
||||
"\n\t\t: where"
|
||||
"\n\t\t: -delete remove animation with specified name"
|
||||
"\n\t\t: -onStart procedure to be called once"
|
||||
"\n\t\t: at the beginning"
|
||||
"\n\t\t: -onEnd procedure to be called once at the end"
|
||||
"\n\t\t: -onRedraw procedure to be called at each frame"
|
||||
"\n\t\t: -addSlice call another animation within specified duration"
|
||||
"\n\t\t: -reset clear list of linked slices"
|
||||
"\n\t\t: Callback procedure should has the following prototype:"
|
||||
"\n\t\t: callback thePts theLocalPts theEvent"
|
||||
"\n\t\t: where"
|
||||
"\n\t\t: -thePts current presentation timestamp"
|
||||
"\n\t\t: -theLocalPts presentation timestamp within slice"
|
||||
"\n\t\t: -theEvent event from the list onStart,onEnd,onRedraw",
|
||||
__FILE__, VAnimation, aGroup);
|
||||
}
|
||||
|
@@ -6295,6 +6295,143 @@ static int VPriority (Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <MeshVS_Mesh.hxx>
|
||||
#include <MeshVS_DataSource.hxx>
|
||||
#include <MeshPresentation.h>
|
||||
// ======================================================================
|
||||
// function : VUpdateVertices
|
||||
// purpose :
|
||||
// ======================================================================
|
||||
static Standard_Integer VUpdateVertices (Draw_Interpretor& theDI,
|
||||
Standard_Integer theArgNum,
|
||||
const char** theArgs)
|
||||
{
|
||||
if (theArgNum < 3)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const TCollection_AsciiString aShapeName (theArgs[1]);
|
||||
const TCollection_AsciiString aNewShapeName (theArgs[2]);
|
||||
|
||||
Standard_Real a = 1.0;
|
||||
Standard_Real k = 1.0;
|
||||
Standard_Real f = 1.0;
|
||||
|
||||
for (Standard_Integer anIter = 3; anIter < theArgNum; ++anIter)
|
||||
{
|
||||
TCollection_AsciiString aValue(theArgs[anIter]);
|
||||
aValue.LowerCase();
|
||||
|
||||
if (aValue == "-a")
|
||||
{
|
||||
if (++anIter >= theArgNum)
|
||||
{
|
||||
theDI << "Syntax error.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
a = Draw::Atof(theArgs[anIter]);
|
||||
}
|
||||
|
||||
if (aValue == "-k")
|
||||
{
|
||||
if (++anIter >= theArgNum)
|
||||
{
|
||||
theDI << "Syntax error.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
k = Draw::Atof(theArgs[anIter]);
|
||||
}
|
||||
|
||||
if (aValue == "-f")
|
||||
{
|
||||
if (++anIter >= theArgNum)
|
||||
{
|
||||
theDI << "Syntax error.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = Draw::Atof(theArgs[anIter]);
|
||||
}
|
||||
}
|
||||
|
||||
TopoDS_Shape aShape = DBRep::Get (theArgs[1]);
|
||||
if (aShape.IsNull())
|
||||
{
|
||||
theDI << "Error: This shape '" << aShapeName << "' is not exist.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
TopLoc_Location aLocation;
|
||||
TopExp_Explorer anExplorer;
|
||||
BRep_Builder aBuilder;
|
||||
TopoDS_Compound aNewShape;
|
||||
|
||||
aBuilder.MakeCompound(aNewShape);
|
||||
|
||||
for (anExplorer.Init (aShape, TopAbs_FACE); anExplorer.More(); anExplorer.Next())
|
||||
{
|
||||
TopoDS_Shape aCurrent = anExplorer.Current();
|
||||
TopoDS_Face& aFace = TopoDS::Face (aCurrent);
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLocation);
|
||||
TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
|
||||
|
||||
for (Standard_Integer anIter = aNodes.Lower(); anIter <= aNodes.Upper(); ++anIter)
|
||||
{
|
||||
const Standard_Real aCurrentZ = aNodes.Value(anIter).Coord().Z();
|
||||
const Standard_Real anAdd = a * sin(k * aNodes.Value(anIter).Coord().Y() + f);
|
||||
|
||||
aNodes.ChangeValue(anIter).ChangeCoord().SetZ (aCurrentZ + anAdd);
|
||||
}
|
||||
|
||||
if (!aTriangulation->HasNormals())
|
||||
{
|
||||
Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(0, 3 * aTriangulation->NbNodes() - 1);
|
||||
aTriangulation->SetNormals(aNormals);
|
||||
}
|
||||
|
||||
if (aTriangulation->HasNormals())
|
||||
{
|
||||
TShort_Array1OfShortReal& aNormals = aTriangulation->ChangeNormals();
|
||||
Standard_ShortReal* aNormArr = &(aNormals.ChangeValue (aNormals.Lower()));
|
||||
|
||||
const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
|
||||
for (Standard_Integer anIter = aTriangles.Lower(); anIter <= aTriangles.Upper(); ++anIter)
|
||||
{
|
||||
Standard_Integer indices[3];
|
||||
aTriangles.Value (anIter).Get (indices[0], indices[1], indices[2]);
|
||||
|
||||
const gp_Pnt& aVertex1 = aNodes.Value (indices[0]);
|
||||
const gp_Pnt& aVertex2 = aNodes.Value (indices[1]);
|
||||
const gp_Pnt& aVertex3 = aNodes.Value (indices[2]);
|
||||
|
||||
const gp_Dir aDir1 (aVertex2.XYZ() - aVertex1.XYZ());
|
||||
const gp_Dir aDir2 (aVertex3.XYZ() - aVertex1.XYZ());
|
||||
const gp_Dir aNormal = aDir1.Crossed(aDir2);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
const Standard_Integer anId = 3 * (indices[i] - aNodes.Lower());
|
||||
aNormArr[anId + 0] = aNormal.X();
|
||||
aNormArr[anId + 1] = aNormal.Y();
|
||||
aNormArr[anId + 2] = aNormal.Z();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aBuilder.Add (aNewShape, aCurrent);
|
||||
}
|
||||
|
||||
DBRep::Set (aNewShapeName.ToCString(), aNewShape);
|
||||
|
||||
TCollection_AsciiString aScript ("vdisplay "); aScript += aNewShapeName;
|
||||
theDI.Eval (aScript.ToCString());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ObjectsCommands
|
||||
//purpose :
|
||||
@@ -6602,4 +6739,8 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
|
||||
"vpriority [-noupdate|-update] name [value]\n\t\t prints or sets the display priority for an object",
|
||||
__FILE__,
|
||||
VPriority, group);
|
||||
|
||||
theCommands.Add("vupdatevertices",
|
||||
"vupdatevertices shapeName newShapeName [-a value] [-k value] [-f value]",
|
||||
__FILE__, VUpdateVertices, group);
|
||||
}
|
||||
|
@@ -4473,21 +4473,7 @@ static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** ar
|
||||
}
|
||||
else if (argc < 2)
|
||||
{
|
||||
di << "Use: vzlayer ";
|
||||
di << " add/del/get/settings/enable/disable [id]\n";
|
||||
di << " add - add new z layer to viewer and print its id\n";
|
||||
di << " del - del z layer by its id\n";
|
||||
di << " get - print sequence of z layers in increasing order of their overlay level\n";
|
||||
di << " settings - print status of z layer settings\n";
|
||||
di << " enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n enables given setting for the z layer\n";
|
||||
di << " enable (p[ositive]offset/n[egative]offset) \n enables given setting for the z layer\n";
|
||||
di << " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n disables given setting for the z layer\n";
|
||||
di << "\nWhere id is the layer identificator\n";
|
||||
di << "\nExamples:\n";
|
||||
di << " vzlayer add\n";
|
||||
di << " vzlayer enable poffset 1\n";
|
||||
di << " vzlayer disable depthtest 1\n";
|
||||
di << " vzlayer del 1\n";
|
||||
di << di.PrintHelp (argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -4625,6 +4611,10 @@ static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** ar
|
||||
{
|
||||
aSettings.SetDepthOffsetNegative();
|
||||
}
|
||||
else if (aSubOp == "textureenv")
|
||||
{
|
||||
aSettings.UseEnvironmentTexture = true;
|
||||
}
|
||||
|
||||
aViewer->SetZLayerSettings (anId, aSettings);
|
||||
}
|
||||
@@ -4662,6 +4652,10 @@ static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** ar
|
||||
{
|
||||
aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
|
||||
}
|
||||
else if (aSubOp == "textureenv")
|
||||
{
|
||||
aSettings.UseEnvironmentTexture = false;
|
||||
}
|
||||
|
||||
aViewer->SetZLayerSettings (anId, aSettings);
|
||||
}
|
||||
@@ -6572,11 +6566,9 @@ static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb,
|
||||
);
|
||||
}
|
||||
aView->SetTextureEnv(aTexEnv);
|
||||
aView->SetSurfaceDetail(V3d_TEX_ENVIRONMENT);
|
||||
}
|
||||
else // Disabling environment mapping
|
||||
{
|
||||
aView->SetSurfaceDetail(V3d_TEX_NONE);
|
||||
Handle(Graphic3d_TextureEnv) aTexture;
|
||||
aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
|
||||
}
|
||||
@@ -6980,40 +6972,6 @@ static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, cons
|
||||
return 1;
|
||||
}
|
||||
|
||||
//===============================================================================================
|
||||
//function : VSetTextureMode
|
||||
//purpose :
|
||||
//===============================================================================================
|
||||
static int VSetTextureMode (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
|
||||
{
|
||||
if (theArgsNb < 3)
|
||||
{
|
||||
theDi << theArgVec[0] << ": insufficient command arguments. Type help for more information.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
TCollection_AsciiString aViewName (theArgVec[1]);
|
||||
if (!ViewerTest_myViews.IsBound1 (aViewName))
|
||||
{
|
||||
theDi << theArgVec[0] << ": view is not found.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Handle(V3d_View)& aView = ViewerTest_myViews.Find1 (aViewName);
|
||||
switch (atoi (theArgVec[2]))
|
||||
{
|
||||
case 0: aView->SetSurfaceDetail (V3d_TEX_NONE); break;
|
||||
case 1: aView->SetSurfaceDetail (V3d_TEX_ENVIRONMENT); break;
|
||||
case 2: aView->SetSurfaceDetail (V3d_TEX_ALL); break;
|
||||
default:
|
||||
theDi << theArgVec[0] << ": invalid mode.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
aView->Redraw();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===============================================================================================
|
||||
//function : VZRange
|
||||
//purpose :
|
||||
@@ -8301,6 +8259,8 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
||||
theDI << "reflections: " << (aParams.IsReflectionEnabled ? "on" : "off") << "\n";
|
||||
theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
|
||||
theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
|
||||
theDI << "samples: " << aParams.SamplesPerPixel << "\n";
|
||||
theDI << "filtering: " << (aParams.IsGIFilteringEnabled ? "on" : "off") << "\n";
|
||||
theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
|
||||
theDI << "shadingModel: ";
|
||||
switch (aView->ShadingModel())
|
||||
@@ -8424,6 +8384,48 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
||||
aParams.RaytracingDepth = aDepth;
|
||||
}
|
||||
}
|
||||
else if (aFlag == "-maxrad"
|
||||
|| aFlag == "-rclamp")
|
||||
{
|
||||
if (toPrint)
|
||||
{
|
||||
theDI << aParams.RadianceClampValue << " ";
|
||||
continue;
|
||||
}
|
||||
else if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
aParams.RadianceClampValue = Draw::Atoi (theArgVec[anArgIter]);
|
||||
}
|
||||
else if (aFlag == "-samples"
|
||||
|| aFlag == "-spp")
|
||||
{
|
||||
if (toPrint)
|
||||
{
|
||||
theDI << aParams.SamplesPerPixel << " ";
|
||||
continue;
|
||||
}
|
||||
else if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Standard_Integer aSamples = Draw::Atoi (theArgVec[anArgIter]);
|
||||
|
||||
if (aSamples < 0)
|
||||
{
|
||||
std::cerr << "Error: invalid ray-tracing samples per pixel " << aSamples << ". SPP should be a positive number.\n";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
aParams.SamplesPerPixel = aSamples;
|
||||
}
|
||||
}
|
||||
else if (aFlag == "-shad"
|
||||
|| aFlag == "-shadows")
|
||||
{
|
||||
@@ -8510,6 +8512,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
||||
aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
|
||||
}
|
||||
}
|
||||
else if (aFlag == "-filter" || aFlag == "-pp" )
|
||||
{
|
||||
if (toPrint)
|
||||
{
|
||||
theDI << (aParams.IsGIFilteringEnabled ? "on" : "off") << " ";
|
||||
continue;
|
||||
}
|
||||
|
||||
Standard_Boolean toEnable = Standard_True;
|
||||
if (++anArgIter < theArgNb
|
||||
&& !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
|
||||
{
|
||||
--anArgIter;
|
||||
}
|
||||
aParams.IsGIFilteringEnabled = toEnable;
|
||||
}
|
||||
else if (aFlag == "-blockedrng"
|
||||
|| aFlag == "-brng")
|
||||
{
|
||||
@@ -8828,6 +8846,69 @@ static Standard_Integer VXRotate (Draw_Interpretor& di,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Standard_Integer VShiftCam (Draw_Interpretor& theDi,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
Handle(V3d_View) anAISView = ViewerTest::CurrentView();
|
||||
if (anAISView.IsNull())
|
||||
{
|
||||
std::cout << theArgVec[0] << ": please initialize or activate view.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Standard_Real anAtX = 0.0;
|
||||
Standard_Real anAtY = 0.0;
|
||||
Standard_Real anAtZ = 0.0;
|
||||
anAISView->At(anAtX, anAtY, anAtZ);
|
||||
|
||||
Standard_Real anEyeX = 0.0;
|
||||
Standard_Real anEyeY = 0.0;
|
||||
Standard_Real anEyeZ = 0.0;
|
||||
anAISView->Eye(anEyeX, anEyeY, anEyeZ);
|
||||
|
||||
Graphic3d_Vec3 aDeltaVec(anAtX - anEyeX, anAtY - anEyeY, anAtZ - anEyeZ);
|
||||
Standard_Real aDelta = Draw::Atof (theArgVec[1]);
|
||||
anAISView->SetEye (anEyeX + aDeltaVec.x() * aDelta,
|
||||
anEyeY + aDeltaVec.y() * aDelta,
|
||||
anEyeZ + aDeltaVec.z() * aDelta);
|
||||
anAISView->SetAt (anAtX + aDeltaVec.x() * aDelta,
|
||||
anAtY + aDeltaVec.y() * aDelta,
|
||||
anAtZ + aDeltaVec.z() * aDelta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Standard_Integer VCamChangeAt (Draw_Interpretor& theDI,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
Handle(V3d_View) anAISView = ViewerTest::CurrentView();
|
||||
if (anAISView.IsNull())
|
||||
{
|
||||
std::cout << theArgVec[0] << ": please initialize or activate view.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Standard_Real anAtX = 0.0;
|
||||
Standard_Real anAtY = 0.0;
|
||||
Standard_Real anAtZ = 0.0;
|
||||
anAISView->At(anAtX, anAtY, anAtZ);
|
||||
|
||||
Standard_Real anEyeX = 0.0;
|
||||
Standard_Real anEyeY = 0.0;
|
||||
Standard_Real anEyeZ = 0.0;
|
||||
anAISView->Eye(anEyeX, anEyeY, anEyeZ);
|
||||
|
||||
Graphic3d_Vec3 aDeltaVec (anAtX - anEyeX, anAtY - anEyeY, anAtZ - anEyeZ);
|
||||
Standard_Real aDelta = Draw::Atof (theArgVec[1]);
|
||||
anAISView->SetAt (anAtX + aDeltaVec.x() * aDelta,
|
||||
anAtY + aDeltaVec.y() * aDelta,
|
||||
anAtZ + aDeltaVec.z() * aDelta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ViewerCommands
|
||||
//purpose :
|
||||
@@ -9023,7 +9104,9 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
|
||||
" settings - print status of z layer settings\n"
|
||||
" enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n enables given setting for the z layer\n"
|
||||
" enable (p[ositive]offset/n[egative]offset) \n enables given setting for the z layer\n"
|
||||
" enable textureenv \n enables environment texture mapping\n"
|
||||
" disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n disables given setting for the z layer\n"
|
||||
" disable textureenv \n disables environment texture mapping\n"
|
||||
"\nWhere id is the layer identificator\n"
|
||||
"\nExamples:\n"
|
||||
" vzlayer add\n"
|
||||
@@ -9278,13 +9361,6 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
|
||||
" change <plane_name> capping hatch on/off/<id> - set hatching mask.\n"
|
||||
" please use VSetTextureMode command to enable texture rendering in view.\n"
|
||||
, __FILE__, VClipPlane, group);
|
||||
theCommands.Add("vsettexturemode", "vsettexturemode view_name mode \n"
|
||||
" mode can be:\n"
|
||||
" 0 - no textures enabled in view.\n"
|
||||
" 1 - only environment textures enabled.\n"
|
||||
" 2 - all textures enabled.\n"
|
||||
" this command sets texture details mode for the specified view.\n"
|
||||
, __FILE__, VSetTextureMode, group);
|
||||
theCommands.Add("vdefaults",
|
||||
"vdefaults [-absDefl value]"
|
||||
"\n\t\t: [-devCoeff value]"
|
||||
@@ -9360,4 +9436,12 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
|
||||
"vprogressive",
|
||||
__FILE__, VProgressiveMode, group);
|
||||
#endif
|
||||
|
||||
theCommands.Add("vshiftcam",
|
||||
"vshiftcam delta",
|
||||
__FILE__, VShiftCam, group);
|
||||
|
||||
theCommands.Add("vcamchangeat",
|
||||
"vcamchangeat delta",
|
||||
__FILE__, VCamChangeAt, group);
|
||||
}
|
||||
|
@@ -839,11 +839,6 @@ static Standard_Integer meshcolors( Draw_Interpretor& di,
|
||||
aBuilder->SetInvalidColor(Quantity_NOC_BLACK);
|
||||
aBuilder->SetTextureCoords(aScaleMap);
|
||||
aMesh->AddBuilder(aBuilder, Standard_True);
|
||||
|
||||
//set viewer to display texures
|
||||
const Handle(V3d_Viewer)& aViewer = anIC->CurrentViewer();
|
||||
for (aViewer->InitActiveViews(); aViewer->MoreActiveViews(); aViewer->NextActiveViews())
|
||||
aViewer->ActiveView()->SetSurfaceDetail(V3d_TEX_ALL);
|
||||
}
|
||||
|
||||
aMesh->GetDrawer()->SetBoolean ( MeshVS_DA_ColorReflection, Standard_Boolean(aReflection) );
|
||||
|
36
tests/bugs/vis/bug26434
Normal file
36
tests/bugs/vis/bug26434
Normal file
@@ -0,0 +1,36 @@
|
||||
puts "============"
|
||||
puts "CR26434"
|
||||
puts "============"
|
||||
puts ""
|
||||
|
||||
##########################################################################################
|
||||
puts "Visualization - Textured objects should have priority over the environment mapping"
|
||||
##########################################################################################
|
||||
|
||||
pload MODELING VISUALIZATION
|
||||
|
||||
vclear
|
||||
vclose all
|
||||
|
||||
vinit View1
|
||||
|
||||
vsetdispmode 1
|
||||
|
||||
box b0 -1 -1 -1 1 2 3
|
||||
box b1 1 1 1 1 2 3
|
||||
|
||||
vdisplay b0 b1
|
||||
vzbufftrihedron
|
||||
|
||||
vfit
|
||||
|
||||
vdump $imagedir/${casename}_0.png
|
||||
|
||||
vtexture b1 0
|
||||
|
||||
vdump $imagedir/${casename}_1.png
|
||||
|
||||
puts "Checking that texture have priority over the environment mapping"
|
||||
vtextureenv on 0
|
||||
|
||||
vdump $imagedir/${casename}_2.png
|
Reference in New Issue
Block a user