Notifications
Clear all

[Closed] Analyzing Viewport Lighting [3DS Max 2014]

sorry for the delay.
i used the svg script from the reference as it is the same method to get the colors like in your first script and it is better to show in a rendering.
It does not have to be 100% precise and the middle of the face is perfect for my case. But as you can see the values differ very much in the script rendering.
Perhaps its just the factor of ambient lighting which needs to be added I look around how this might work.
Why does the lighting depend on the vewing angle? A very matt surface without reflections should not change depending on perspective if I imagine a real world scenario.

thank alot.

The SVG renderer does not take into account the light multiplier, but I added it to the script. I suppose you are not using a multiplier of 1.0, and so the render comes out different. The first script should work though.

You can modify the SVG code by multiplying the resulting color by the light multiplier.

Note that the script does also not take into account the ambient light, but it wouldn’t be hard to add it.

Regarding the viewing and light angles, I meant if you are using specular and glossiness values other than 0.0. If you only use the diffuse value, the color shouldn’t change much, perhaps you would see a very soft gradient. You could also turn off affect specular in the light parameters just to be sure it is not affecting the material.

What values do you get with the first script for that same example? They should be lighter than the SVG image.

As I mentioned earlier, it would be useful a sample scene, so I can reproduce the results you get, because in my test, it seems to
work well.

the multiplier is 1.0, the values I get from script one are wrong…
here is my testfile https://app.box.com/s/md4y9kzikt0p60ypc5ivrud5uhnmok0h

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

Your scene is gamma corrected so you should correct the output colors as well.
The formula for gamma correction is:

color = 255 * (color/255.0)^(1/2.2)

Besides Gamma correction, your scene also has Exposure Control, so you must use the same exposure algorithm to correct the output colors.

Considering the amount of variables you need to handle, based on your scene, I think it would be faster to just use the viewports images to get the colors instead of building a pseudo render engine. Not the best approach, but see if this code helps you.

You need to select 2 viewports (for front and back faces) as you described, and then enable it.

Keep in mind that any other visible stuff in the scene can alter the colors, so you better hide everything you can before getting the image. You could add some code to hide things like grid, lights, cameras, etc. to the code if you want.

Hope it helps.


(

    try destroydialog ::RO_DISPLAY_FACES_COLORS catch()

    rollout RO_DISPLAY_FACES_COLORS "Faces Colors" width:172 height:124
    (
        button       bt_vp1 "Set View 1" pos:[ 8,8] width:72 height:32
        button       bt_vp2 "Set View 2" pos:[88,8] width:72 height:32
        
        radioButtons rdo1 "Display:" pos:[8,48] labels:#("RGB","H","S","B") columns:4
        checkbutton  btn1 "Enable"   pos:[8,88] width:154 height:28
        timer        clock interval:20 active:false

        global GW_DisplayFacesColors

        local GetFaceVerts = polyop.getfaceverts
        local GetfaceNormal = polyop.getfaceNormal
        local GetFaceCenter = polyop.getFaceCenter
        local GetVert = polyop.getvert
        local node
        local vp_front = undefined
        local vp_back  = undefined
        local data_front = #()
        local data_back  = #()
        local ViewPanelHwnd = 0
        
        fn GetViewportsPanelHWND =
        (
            for j in (windows.getchildrenhwnd #max) where j[4] == "ViewPanel" do exit with j[1]
        )

        fn CalculateFacesColors =
        (
            dib = gw.getViewportDib()

            viewTM = viewport.getTM()
            viewTM.row4 = [0,0,0]

            gw.setTransform (matrix3 1)

            result = for f = 1 to node.numfaces collect
            (
                faceNormal = normalize (GetfaceNormal node f)

                if (faceNormal*viewTM).z > 0 then
                (
                    faceCenter = GetFaceCenter node f
                    fverts = GetFaceVerts node f

                    verts = for j in fverts collect (faceCenter + (GetVert node j)) / 2.0
                    append verts faceCenter
                    numverts = verts.count

                    faceColor = black

                    for j in verts do
                    (
                        px = gw.transPoint j
                        if px.x > 1 and px.y < dib.width do
                        (
                            pcolor = (getpixels dib [px[1], px[2]] 1)[1]
                            if pcolor != undefined then faceColor += pcolor else numverts -= 1
                        )
                    )
                    
                    faceColor.r = faceColor.r/numverts
                    faceColor.g = faceColor.g/numverts
                    faceColor.b = faceColor.b/numverts
                    
                    if iDisplayGamma.colorCorrectionMode == #gamma do
                    (
                        faceColor.r = 255 * (faceColor.r / 255.0)^(1/IDisplayGamma.gamma)
                        faceColor.g = 255 * (faceColor.g / 255.0)^(1/IDisplayGamma.gamma)
                        faceColor.b = 255 * (faceColor.b / 255.0)^(1/IDisplayGamma.gamma)
                    )
                    
                    faceColor.r = int faceColor.r
                    faceColor.g = int faceColor.g
                    faceColor.b = int faceColor.b
                    
                    #(faceCenter, faceColor)
                )else(
                    dontcollect
                )
            )

            free dib

            return result
        )

        on clock tick do
        (
            if viewport.numViews < vp_front or viewport.numViews < vp_back then
            (
                data_front = CalculateFacesColors()
                data_back = #()
            )else(
                activeVP = viewport.activeViewport
                windows.sendmessage ViewPanelHwnd 11 0 0    -- redraw off
                
                viewport.ActiveViewportEx vp_front
                data_front = CalculateFacesColors()
                
                viewport.ActiveViewportEx vp_back
                data_back = CalculateFacesColors()
                
                viewport.ActiveViewportEx activeVP
                windows.sendmessage ViewPanelHwnd 11 1 0    -- redraw on
            )
        )

        fn GW_DisplayFacesColors =
        (
            for j in data_front do
            (
                val = case rdo1.state of
                (
                    1: j[2] as point3
                    2: int j[2].h
                    3: int j[2].s
                    4: int j[2].v
                )
                gw.text j[1] (val as string) color:blue
            )
            
            for j in data_back do
            (
                val = case rdo1.state of
                (
                    1: j[2] as point3
                    2: int j[2].h
                    3: int j[2].s
                    4: int j[2].v
                )
                gw.text j[1] (val as string) color:red
            )
            gw.enlargeUpdateRect #whole
        )

        on RO_DISPLAY_FACES_COLORS open do
        (
            unregisterRedrawViewsCallback GW_DisplayFacesColors
            completeredraw()
        )

        on RO_DISPLAY_FACES_COLORS close do
        (
            unregisterRedrawViewsCallback GW_DisplayFacesColors
            completeredraw()
        )

        on btn1 changed arg do
        (
            if vp_front == undefined or vp_back == undefined do return messagebox "Select View 1 and 2"
            
            unregisterRedrawViewsCallback GW_DisplayFacesColors
            if arg then
            (
                if selection.count == 1 and iskindof selection[1] editable_poly then
                (
                    ViewPanelHwnd = GetViewportsPanelHWND()
                    node = selection[1]
                    clock.tick()
                    clock.active = true
                    registerRedrawViewsCallback GW_DisplayFacesColors
                )else(
                    node = undefined
                    btn1.checked = false
                    clock.active = false
                    messagebox "Select an object"
                )
            )else(
                clock.active = false
            )
            completeredraw()
        )

        on rdo1 changed arg do completeredraw()
        
        on bt_vp1 pressed do
        (
            vp_front = viewport.activeViewport
            bt_vp1.text = vp_front as string
        )
        
        on bt_vp2 pressed do
        (
            vp_back = viewport.activeViewport
            bt_vp2.text = vp_back as string
        )

    )

    createdialog RO_DISPLAY_FACES_COLORS
)

wow Thank you thats much more than i expected.
It is almost done. Now the last problem is that the User interface is flickering and partly unusable when the activeViewport changed all the time mhh.
I tried to find the exposure control algorithm but i had no luck so far. Do you have any Plan on where to look for it?
What all of this is for : The Project am on is about transferring a virtual light situation onto a real object by measuring-> setting the light on each face.

If the screen flickers then the WM_SETREDRAW message mightnot be working on your system. On my end I see no flickering in any Max version I could test, and I can navigate the viewports normally.

I tested it on Windows 7, perhaps you are using Windows 10?You’ll need to find the correct message in order to set the redraw on/off.

Other than that, the script is like 90% done if you wouldlike to avoid any “hack” using messages, you could use the C# API, which allows you to get the BID of a non-active viewport.

Regarding the Exposure algorithm, I would try the SDKexamples, but I think it is not there. Perhaps you should open a different thread about the Logarithmic Exposure Control and how to do it in MXS? It seems it is a custom algorithm so is not going to be so easy to re-build. The Brightness and Contrast parameters could be just standard, but I don’t know how the other values scale the colors.

I also use win 7 with the following .net versions installed :

They flickering is there I can see the yellow border of the active viewport switch between the viewports. I cannot really interact with the toolbar on the bottom right to turn around or so.
which .net version do you use?

I don’t know what can cause the flickering on your end, but I don’t think is .Net related. The script just sends a standard Windows message. Perhaps is video card or driver related, I can’t tell.
You could try with windows.postMessage() instead of sendmessage().
Or try sending just the messages to enable/disable the redraw and see if they work.

Page 2 / 4