[NTG-context] 3D annotations

Michail Vidiassov master at iaas.msu.ru
Sat Apr 17 09:00:58 CEST 2010


Dear Hans,

I wrote to you
> thank you for your latest effort to put u3d support in a working state, but

more thanks for more effort, but

> May be a more robust way is to read first 3 bytes of the model file, since
> "U3D" or "PRC" signature is always there - that can be done instead of 
> relying on file name extension or only in case it it not "u3d" or "prc".

you have implemented reading the file signature, but it is now 
almost useless, since if a file has extension other but U3D or PRC
3D annotation code will not be called by file inclusion mechanism
and "io.readdata" routine is called
local subtype, subdata = "U3D", io.readdata(foundname) or ""
- what's that?

One more point - preview bitmap images in 3D annotations are now disabled
since necessary functionality of measuring XForms is missing -
please, consider the following workaround.

--- lpdf-u3d.lua.org	2010-03-26 18:24:44.000000000 +0300
+++ lpdf-u3d.lua	2010-04-14 14:24:28.000000000 +0400
@@ -17,6 +17,7 @@
  local cos, sin, sqrt, pi, atan2, abs = math.cos, math.sin, math.sqrt, math.pi, math.atan2, math.abs

  local pdfconstant   = lpdf.constant
+local pdfnumber     = lpdf.number
  local pdfboolean    = lpdf.boolean
  local pdfunicode    = lpdf.unicode
  local pdfdictionary = lpdf.dictionary
@@ -62,8 +63,7 @@

  local function make3dview(view)

-    local name = viewname
-    local name = pdfunicode((view.name ~= "" and name) or "unknown view")
+    local name = pdfunicode((view.name ~= "" and view.name) or "unknown view")

      local viewdict = pdfdictionary {
         Type = pdfconstant("3DView"),
@@ -311,9 +311,6 @@
          for i=1,#nodes do
              local node = checkedkey(nodes,i,"table")
              if node then
-                local position = checkedkey(node,"position","table")
-                position = position and #position == 12 and pdfarray(position)
-                if position then
                      nodelist[#nodelist+1] = pdfdictionary {
                          Type = pdfconstant("3DNode"),
                          N    = node.name or ("node_" .. i), -- pdfunicode ?
@@ -325,13 +322,18 @@
                          },
                          M    = position,
                      }
+                local position = checkedkey(node,"position","table")
+                position = position and #position == 12 and pdfarray(position)
+                if position then
+                    nodelist[#nodelist].M = position
                  end
              end
        end
-      viewdict.NR = true
        viewdict.NA = nodelist
     end

+    viewdict.NR = true
+
     return viewdict

  end
@@ -349,19 +351,19 @@

      local activationdict = pdfdictionary {
         TB = pdfboolean(param.toolbar,true),
-       NP = pdfboolean(param.tree,true),
+       NP = pdfboolean(param.tree,false),
      }

      local stream = streams[label]
      if not stream then

-        local subtype, subdata = "U3D", io.readdata(foundname) or ""
+        local subtype, subdata = "U3D", file.readdata(foundname) or ""
          if find(subdata,"^PRC") then
-            subtype == "PRC"
+            subtype = "PRC"
          elseif find(subdata,"^U3D") then
-            subtype == "U3D"
+            subtype = "U3D"
          elseif file.extname(foundname) == "prc" then
-            subtype == "PRC"
+            subtype = "PRC"
          end

          local attr = pdfdictionary {
@@ -423,12 +425,35 @@
          local ref = stored_pr[tag]
          if not ref then
          --  weird, has to be a /Form and not an /Image so we need a wrap = true key
-        --  local figure = img.immediatewrite { filename = preview, width = width, height = height }
-            local figure = img.immediatewrite { stream = ".5 .75 .75 rg 0 0 20 10 re f", bbox = {0,0,20,10 } }
+            local figure = img.immediatewrite { filename = preview, width = width, height = height }
+        --  local figure = img.immediatewrite { stream = ".5 .75 .75 rg 0 0 20 10 re f", bbox = {0,0,20,10 } }
              ref = figure.objnum
              stored_pr[tag] = ref
          end
-        annot.AP = ref and pdfdictionary { N = pdfreference(ref) }
+        if ref then
+            local pw   = pdfdictionary {
+                Type      = pdfconstant("XObject"),
+                Subtype   = pdfconstant("Form"),
+                FormType  = pdfnumber(1),
+                BBox      = pdfarray { pdfnumber(0), pdfnumber(0), pdfnumber(factor*width), pdfnumber(factor*height) },
+                Matrix    = pdfarray { pdfnumber(1), pdfnumber(0), pdfnumber(0), pdfnumber(1), pdfnumber(0), pdfnumber(0) },
+                Resources = pdfdictionary {
+                                XObject = pdfdictionary {
+                                    IM = pdfreference(ref)
+                                }
+                            },
+                ExtGState = pdfdictionary {
+                                GS = pdfdictionary {
+                                    Type = pdfconstant("ExtGState"),
+                                    CA   = pdfnumber(1),
+                                    ca   = pdfnumber(1)
+                                }
+                            },
+                ProcSet    = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") },
+            }
+            local pwd = pdf.immediateobj("stream",format("q /GS gs %s 0 0 %s 0 0 cm /IM Do Q",factor*width,factor*height),pw())
+            annot.AP = pdfdictionary { N = pdfreference(pwd) }
+        end
          return annot, figure, ref
      else
          activationdict.A = pdfconstant("PV")

Also I try to remind you AGAIN and AGAIN about pdfboolean problem in 
lpdf-ini.lua (old code is not OK if b is "false" and default is "true")

  local function pdfboolean(b,default)
-    if ((type(b) == "boolean") and b) or default then
-        return p_true
+    if type(b) ~= "boolean" then
+        if default then
+            return p_true
+        else
+            return p_false
+        end
      else
-        return p_false
+        if b then
+            return p_true
+        else
+            return p_false
+        end
      end
  end

        Sincerely, Michail

PS. And a great palliative way to deal with 3D annotations is via
attaching a 3D PDF file made with LaTeX (by Asymptote, for example).

But while your method of answering my messages in lua works OK for
new code (updating minimals and making a diff with old code is not
harder than checking e-mail inbox - "Your morning patch, sir!" ;),
I can not deduce from existing sea of ConTeXt code the status of file 
attachments support.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testprc.tgz
Type: application/octet-stream
Size: 29627 bytes
Desc: 
URL: <http://www.ntg.nl/pipermail/ntg-context/attachments/20100417/a35f5221/attachment-0001.obj>
-------------- next part --------------
--- lpdf-u3d.lua.org	2010-03-26 18:24:44.000000000 +0300
+++ lpdf-u3d.lua	2010-04-14 14:24:28.000000000 +0400
@@ -17,6 +17,7 @@
 local cos, sin, sqrt, pi, atan2, abs = math.cos, math.sin, math.sqrt, math.pi, math.atan2, math.abs
 
 local pdfconstant   = lpdf.constant
+local pdfnumber     = lpdf.number
 local pdfboolean    = lpdf.boolean
 local pdfunicode    = lpdf.unicode
 local pdfdictionary = lpdf.dictionary
@@ -62,8 +63,7 @@
 
 local function make3dview(view)
 
-    local name = viewname
-    local name = pdfunicode((view.name ~= "" and name) or "unknown view")
+    local name = pdfunicode((view.name ~= "" and view.name) or "unknown view")
 
     local viewdict = pdfdictionary {
        Type = pdfconstant("3DView"),
@@ -311,9 +311,6 @@
         for i=1,#nodes do
             local node = checkedkey(nodes,i,"table")
             if node then
-                local position = checkedkey(node,"position","table")
-                position = position and #position == 12 and pdfarray(position)
-                if position then
                     nodelist[#nodelist+1] = pdfdictionary {
                         Type = pdfconstant("3DNode"),
                         N    = node.name or ("node_" .. i), -- pdfunicode ?
@@ -325,13 +322,18 @@
                         },
                         M    = position,
                     }
+                local position = checkedkey(node,"position","table")
+                position = position and #position == 12 and pdfarray(position)
+                if position then
+                    nodelist[#nodelist].M = position
                 end
             end
       end
-      viewdict.NR = true
       viewdict.NA = nodelist
    end
 
+    viewdict.NR = true
+
    return viewdict
 
 end
@@ -349,19 +351,19 @@
 
     local activationdict = pdfdictionary {
        TB = pdfboolean(param.toolbar,true),
-       NP = pdfboolean(param.tree,true),
+       NP = pdfboolean(param.tree,false),
     }
 
     local stream = streams[label]
     if not stream then
 
-        local subtype, subdata = "U3D", io.readdata(foundname) or ""
+        local subtype, subdata = "U3D", file.readdata(foundname) or ""
         if find(subdata,"^PRC") then
-            subtype == "PRC"
+            subtype = "PRC"
         elseif find(subdata,"^U3D") then
-            subtype == "U3D"
+            subtype = "U3D"
         elseif file.extname(foundname) == "prc" then
-            subtype == "PRC"
+            subtype = "PRC"
         end
 
         local attr = pdfdictionary {
@@ -423,12 +425,35 @@
         local ref = stored_pr[tag]
         if not ref then
         --  weird, has to be a /Form and not an /Image so we need a wrap = true key
-        --  local figure = img.immediatewrite { filename = preview, width = width, height = height }
-            local figure = img.immediatewrite { stream = ".5 .75 .75 rg 0 0 20 10 re f", bbox = {0,0,20,10 } }
+            local figure = img.immediatewrite { filename = preview, width = width, height = height }
+        --  local figure = img.immediatewrite { stream = ".5 .75 .75 rg 0 0 20 10 re f", bbox = {0,0,20,10 } }
             ref = figure.objnum
             stored_pr[tag] = ref
         end
-        annot.AP = ref and pdfdictionary { N = pdfreference(ref) }
+        if ref then
+            local pw   = pdfdictionary {
+                Type      = pdfconstant("XObject"),
+                Subtype   = pdfconstant("Form"),
+                FormType  = pdfnumber(1),
+                BBox      = pdfarray { pdfnumber(0), pdfnumber(0), pdfnumber(factor*width), pdfnumber(factor*height) },
+                Matrix    = pdfarray { pdfnumber(1), pdfnumber(0), pdfnumber(0), pdfnumber(1), pdfnumber(0), pdfnumber(0) },
+                Resources = pdfdictionary {
+                                XObject = pdfdictionary {
+                                    IM = pdfreference(ref)
+                                }
+                            },
+                ExtGState = pdfdictionary {
+                                GS = pdfdictionary {
+                                    Type = pdfconstant("ExtGState"),
+                                    CA   = pdfnumber(1),
+                                    ca   = pdfnumber(1)
+                                }
+                            },
+                ProcSet    = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") },
+            }
+            local pwd = pdf.immediateobj("stream",format("q /GS gs %s 0 0 %s 0 0 cm /IM Do Q",factor*width,factor*height),pw())
+            annot.AP = pdfdictionary { N = pdfreference(pwd) }
+        end
         return annot, figure, ref
     else
         activationdict.A = pdfconstant("PV")
-------------- next part --------------
--- lpdf-ini.lua.org	2010-04-07 19:51:31.000000000 +0400
+++ lpdf-ini.lua	2010-03-25 20:33:27.000000000 +0300
@@ -278,10 +280,18 @@
 end
 
 local function pdfboolean(b,default)
-    if ((type(b) == "boolean") and b) or default then
-        return p_true
+    if type(b) ~= "boolean" then
+        if default then
+            return p_true
+        else
+            return p_false
+        end
     else
-        return p_false
+        if b then
+            return p_true
+        else
+            return p_false
+        end
     end
 end
 


More information about the ntg-context mailing list